Recursive AI

Report errors with line and column

All oneyaml C# recipes

Validate a YAML file and say exactly what’s wrong and where. Every OneYaml error is a YamlException with the position, a category to switch on and, for a value, the JSON Pointer path to it.

C#
using OneYaml;
 
// Malformed YAML: line, column and a category to switch on.
Report(() => YamlDocument.Parse("name: web\nports: [80, 443\n").Dispose());
 
// A duplicate key.
Report(() => YamlSerializer.Deserialize<object>("name: web\nname: api\n"));
 
// A value that doesn't fit its type: the path to it, too.
Report(() => YamlSerializer.Deserialize<Config>("port: 99999\ndebug: yes\n"));
 
static void Report(Action read)
{
    try
    {
        read();
    }
    catch (YamlException e)
    {
        Console.WriteLine($"{e.Line}:{e.Column} {e.Category} {e.Path}");
        Console.WriteLine($"  {e.Message}");
    }
}
 
record Config(ushort Port, bool Debug);
Text
3:1 Syntax 
  Expected ',' or ']' in the flow sequence. (line 3, column 1)
2:1 DuplicateKey /name
  The key 'name' appears twice in the mapping. (line 2, column 1, path /name)
1:7 Binding /port
  The number '99999' is outside the range of an unsigned 16-bit integer. (line 1, column 7, path /port)

Good to know

  • Line and Column are 1-based; Offset is the position in the input. Path is the JSON Pointer to the value, when there is one.
  • Switch on Category, not on the message: Syntax, DuplicateKey, Binding, Limit, PatchTest, RefusedAlias and the others.
  • Message already includes the position and path, so it reads well in a log. Set SourceName in the options to put the file name in front of it.
  • A read stops at the first error. To check every key a type doesn’t have, set UnmappedMemberHandling = YamlUnmappedMemberHandling.Disallow (parse YAML into classes).