Recursive AI

Report errors with line and column

All oneyaml Rust recipes

Validate a YAML file and say exactly what’s wrong and where. Every oneyaml error has a stable Y#### code, a position and, for typed reads, the path to the value.

RUST
use oneyaml::{ColumnUnit, Document, LineIndex};
use serde::Deserialize;
 
#[derive(Debug, Deserialize)]
struct Config {
    #[allow(dead_code)]
    port: u16,
}
 
fn main() {
    // A typed read: the error has a code, a position and a path.
    let src = "port: 99999\n";
    let err = oneyaml::from_str::<Config>(src).unwrap_err();
    let at = err.location().expect("a position");
    println!("{} at line {}, column {}", err.code(), at.line(), at.column());
    println!("path: {}", err.path().map(|p| p.to_string()).unwrap_or_default());
    println!("one line: {err}");
 
    // Or the rustc-style snippet, for a terminal.
    print!("{}", err.render(src));
 
    // Every error in a file, not only the first.
    let src = "name: web\nname: api\nports: [80, 443\n";
    let parsed = Document::parse_recovering(src);
    let lines = LineIndex::new(src);
    for d in parsed.diagnostics() {
        let at = lines.line_col(d.primary.span.start, ColumnUnit::Char).expect("in bounds");
        println!("{}:{}: {} {}", at.line + 1, at.column + 1, d.code, d.message);
    }
}
Text
Y3001 at line 1, column 7
path: port
one line: integer 99999 is out of range for u16 at port (1:7)
error[Y3001]: integer 99999 is out of range for u16
 --> 1:7
  |
1 | port: 99999
  |       ^^^^^
  |
  = path: port
2:1: Y1013 duplicate key `name`
4:1: Y0022 flow collection is not closed

Good to know

  • err.location() gives a 1-based line and column (in characters) and the byte offset. err.span() gives the byte range.
  • Codes are stable. Match on err.code() (or err.kind() for the broad category), not on the message. Codes are never reused.
  • Fixes come with many errors. err.diagnostic().suggestions holds suggested fixes you can apply with fix.apply(src). A fix is marked machine-applicable only when it can’t change what the rest of the file means.
  • Document::parse_recovering keeps going past the first error and returns the document with every diagnostic. render_diagnostics prints them all as snippets.
  • With the miette feature, Error implements miette::Diagnostic, for miette’s reports.

More in diagnostics.