Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Errors: the schema

These errors come from the schema file itself: its YAML, its keys and their values, and its regular expressions. Section 3 of the core specification defines these errors. A separate page lists the errors for the shapes and the templates of its rules.

TL_12

The schema contains a key that the grammar doesn’t define for the map that holds it (TL_12).

Message

<file>:<line>: error[TL_12]: unknown key `<key>` in `<rule map>`
<file>:<line>: error[TL_12]: unknown key `heading-from` in `section` (`heading-from: <key>` became `heading: { from: <key> }`)

Cause

The command checks the schema against the grammar before it uses the schema. Each map of a schema accepts only the keys that the grammar defines for it. A misspelled key is unknown, and so is a key that belongs to another kind of map. In the message, <rule map> names the kind of map that holds the key, such as schema, section, block, or format.

Fix

Change the schema. Correct the spelling of the key, move it to the map where it belongs, or remove it. The schema keys reference lists each key and the maps that accept it.

Example

This schema misspells optional:

note.yaml

line-limit: 0
sections:
  - heading: Note
    level: 1
    blocks: []
  - heading: Links
    level: 2
    optinal: true
    blocks: []

note.md

# Note
$ tramlines validate --schema note.yaml note.md
note.yaml:8: error[TL_12]: unknown key `optinal` in `section`
1 error, 0 warnings
[exit 1]

Spell the key correctly:

note.yaml

line-limit: 0
sections:
  - heading: Note
    level: 1
    blocks: []
  - heading: Links
    level: 2
    optional: true
    blocks: []
$ tramlines validate --schema note.yaml note.md
0 errors, 0 warnings

TL_101

A value of the schema doesn’t have the type that the grammar defines for its key (TL_101).

Message

<file>:<line>: error[TL_101]: `<rule map>` must be a map, not a <type>
<file>:<line>: error[TL_101]: `<key>` must be an integer
<file>:<line>: error[TL_101]: `<key>` must be true or false
<file>:<line>: error[TL_101]: `<key>` must be a list
<file>:<line>: error[TL_101]: `<key>` must be a map
<file>:<line>: error[TL_101]: `<key>` must be a string, not a <type>
<file>:<line>: error[TL_101]: `<key>` must be a string or a list
<file>:<line>: error[TL_101]: `<key>` must be a string or a map
<file>:<line>: error[TL_101]: `<key>` must be a string or `{ from: <frontmatter key> }`
<file>:<line>: error[TL_101]: `<key>` must be a string, `{ from: <frontmatter key> }` or a `<rule map>` map
<file>:<line>: error[TL_101]: `<key>` items must be strings
<file>:<line>: error[TL_101]: `<key>` items must be integers
<file>:<line>: error[TL_101]: `<key>` items must be booleans
<file>:<line>: error[TL_101]: `<key>` values must be strings or lists of strings
<file>:<line>: error[TL_101]: `types` must be a map of types
<file>:<line>: error[TL_101]: type `<name>` must be a regex or a list of choices
<file>:<line>: error[TL_101]: type `<name>`: a list of choices holds one or more non-empty strings
<file>:<line>: error[TL_101]: the format registry must be a map of formats

Cause

The grammar gives each key a type: a number, true or false, a string, a list, or a map. The value in the schema is of another type, such as a word where the key takes a number, or a single string where the key takes a list.

Fix

Change the schema. Write the value in the type that the message states. The schema keys reference lists the type of each key.

Example

This schema sets level to a word instead of a number:

note.yaml

line-limit: 0
sections:
  - heading: Note
    level: one
    blocks: []

note.md

# Note
$ tramlines validate --schema note.yaml note.md
note.yaml:4: error[TL_101]: `level` must be an integer
1 error, 0 warnings
[exit 1]

Write the level as a number:

note.yaml

line-limit: 0
sections:
  - heading: Note
    level: 1
    blocks: []
$ tramlines validate --schema note.yaml note.md
0 errors, 0 warnings

TL_102

A value of the schema has the right type, but it isn’t one of the values that its key allows (TL_102).

Message

<file>:<line>: error[TL_102]: `<key>` must be one of <values>; `<value>` is not
<file>:<line>: error[TL_102]: `<key>` must be a slug: `<value>` is not
<file>:<line>: error[TL_102]: type `<name>` must be named by a slug
<file>:<line>: error[TL_102]: template `<template>`: `seq-width` must be positive

Cause

Some keys take only a value from a list, such as kind, which names a kind of block. Others, such as rule-id and the name of a type, take only a slug: a string of lowercase letters, digits, and hyphens. A seq-width must be 1 or more.

Fix

Change the schema. Write one of the values that the message lists, write the value or the name of the type as a slug, or set seq-width to 1 or more.

Example

This schema names a kind of block that doesn’t exist:

note.yaml

line-limit: 0
sections:
  - heading: Note
    level: 1
    blocks:
      - kind: paragraph
        example: Buy milk.

note.md

# Note

Buy milk.
$ tramlines validate --schema note.yaml note.md
note.yaml:6: error[TL_102]: `kind` must be one of `prose`, `bullet-list`, `numbered-list`, `table`, `code`, `blockquote`, `image`, `html`, `thematic-break`, `references`, `group`; `paragraph` is not
1 error, 0 warnings
[exit 1]

Use the kind prose:

note.yaml

line-limit: 0
sections:
  - heading: Note
    level: 1
    blocks:
      - kind: prose
        example: Buy milk.
$ tramlines validate --schema note.yaml note.md
0 errors, 0 warnings

TL_103

A map of the schema lacks a key that the grammar requires (TL_103).

Message

<file>:<line>: error[TL_103]: `<rule map>` requires `<key>`
<file>:<line>: error[TL_103]: `<key>` requires `<other key>` beside it
<file>:<line>: error[TL_103]: `<rule map>` needs at least one of <keys>
<file>:<line>: error[TL_103]: `<rule map>` needs exactly one of <keys>
<file>:<line>: error[TL_103]: `lines-open` without `lines`

Cause

The grammar requires some keys in every map of a kind, such as line-limit in the schema and level in a section. Some keys need another key beside them, such as number-from-parent, which needs parent. Some maps need one key of a group, such as a key-derives-from, which takes rule or from. The map in the schema lacks the key, or has no key of the group.

Fix

Change the schema. Add the key that the message names, or one key of the group that it lists. If the schema doesn’t need a key that requires another, remove that key.

Example

This schema has no line-limit:

note.yaml

sections:
  - heading: Note
    level: 1
    blocks: []

note.md

# Note
$ tramlines validate --schema note.yaml note.md
note.yaml:1: error[TL_103]: `schema` requires `line-limit`
1 error, 0 warnings
[exit 1]

Add the limit. A limit of 0 sets none:

note.yaml

line-limit: 0
sections:
  - heading: Note
    level: 1
    blocks: []
$ tramlines validate --schema note.yaml note.md
0 errors, 0 warnings

TL_104

A map of the schema contains more than one key of a group that allows only one (TL_104).

Message

<file>:<line>: error[TL_104]: `<rule map>` needs exactly one of <keys>

Cause

Some maps take exactly one key of a group. A key-derives-from, for example, takes its prefixes either from a rule, with rule, or from a frontmatter key, with from. The map in the schema contains two keys of that group. Two shapes on one rule cause a separate error, TL_22.

Fix

Change the schema. Keep one key of the group that the message lists, and remove the others.

Example

This key-derives-from names both a rule and a frontmatter key:

note.yaml

line-limit: 0
types:
  code: '[A-Z]+-[0-9]+'
frontmatter:
  code:
    example: NOTE
sections:
  - heading: Note
    level: 1
    blocks:
      - kind: bullet-list
        each:
          template: '${id:code} ${}'
          key: id
          key-derives-from: { rule: other, from: code, separator: '-' }
          example: NOTE-1 Buy milk

note.md

---
code: NOTE
---

# Note

- <a id="note-1"></a>NOTE-1 Buy milk
$ tramlines validate --schema note.yaml note.md
note.yaml:15: error[TL_104]: `key-derivation` needs exactly one of `rule`, `from`
1 error, 0 warnings
[exit 1]

Keep from:

note.yaml

line-limit: 0
types:
  code: '[A-Z]+-[0-9]+'
frontmatter:
  code:
    example: NOTE
sections:
  - heading: Note
    level: 1
    blocks:
      - kind: bullet-list
        each:
          template: '${id:code} ${}'
          key: id
          key-derives-from: { from: code, separator: '-' }
          example: NOTE-1 Buy milk
$ tramlines validate --schema note.yaml note.md
0 errors, 0 warnings

TL_13

The schema file isn’t valid YAML, so the command can’t read it and stops (TL_13).

Message

error[TL_13]: <file>: YAML does not parse at line <line>: <reason>
error[TL_13]: <file>: YAML mapping key at line <line> is not a string

Cause

The command reads the schema as YAML 1.2 with the core schema. A syntax error, such as a quote that isn’t closed or a key that appears twice in one map, stops the command with exit code 2 before it checks anything. A map key that isn’t a string stops it the same way. An anchor, an alias, or a tag causes a separate error, TL_14.

Fix

Fix the YAML of the schema at the line that the message names.

Example

This schema opens a quote and doesn’t close it:

note.yaml

line-limit: 0
sections:
  - heading: "Note
    level: 1
    blocks: []

note.md

# Note
$ tramlines validate --schema note.yaml note.md
error[TL_13]: note.yaml: YAML does not parse at line 3: invalid indentation in quoted scalar
[exit 2]

Close the quote:

note.yaml

line-limit: 0
sections:
  - heading: "Note"
    level: 1
    blocks: []
$ tramlines validate --schema note.yaml note.md
0 errors, 0 warnings

TL_14

The schema or the formats file uses a YAML anchor, alias, or tag, which neither file can contain, so the command stops (TL_14).

Message

error[TL_14]: <file>: YAML anchor at line <line>: anchors are not read
error[TL_14]: <file>: YAML alias at line <line>: aliases are not read
error[TL_14]: <file>: YAML tag at line <line>: tags are not read

Cause

An anchor (&name) names a value, and an alias (*name) repeats it. A tag (!name) gives a value a type. A schema, and the formats file that --formats names, can’t use any of them: each value must appear in full where it’s written. The command stops with exit code 2 before it checks anything.

Fix

Change the file that the message names. Write out in full each value that an alias repeats, and remove the anchor and any tag.

Example

This schema anchors the level of one section and repeats it in another with an alias:

note.yaml

line-limit: 0
sections:
  - heading: Note
    level: &top 1
    blocks: []
  - heading: Summary
    level: *top
    blocks: []

note.md

# Note

# Summary
$ tramlines validate --schema note.yaml note.md
error[TL_14]: note.yaml: YAML anchor at line 4: anchors are not read
[exit 2]

Write the level out each time:

note.yaml

line-limit: 0
sections:
  - heading: Note
    level: 1
    blocks: []
  - heading: Summary
    level: 1
    blocks: []
$ tramlines validate --schema note.yaml note.md
0 errors, 0 warnings

TL_15

Two rules of the schema declare the same rule-id (TL_15).

Message

<file>:<line>: error[TL_15]: `rule-id` `<id>` is declared twice

Cause

Other rules refer to a rule by its rule-id, so each rule-id must name exactly one rule. The message names the id, on the line of the second rule that declares it.

Fix

Change the schema. Give one of the two rules another rule-id, and update each reference to that rule.

Example

Both sections of this schema declare rule-id: note:

note.yaml

line-limit: 0
sections:
  - heading: Note
    level: 1
    rule-id: note
    blocks: []
  - heading: Notes
    level: 2
    rule-id: note
    optional: true
    blocks: []

note.md

# Note
$ tramlines validate --schema note.yaml note.md
note.yaml:7: error[TL_15]: `rule-id` `note` is declared twice
1 error, 0 warnings
[exit 1]

Rename the second one:

note.yaml

line-limit: 0
sections:
  - heading: Note
    level: 1
    rule-id: note
    blocks: []
  - heading: Notes
    level: 2
    rule-id: notes
    optional: true
    blocks: []
$ tramlines validate --schema note.yaml note.md
0 errors, 0 warnings

TL_118

A regular expression in the schema, or the expression that a template compiles to, doesn’t compile in the regular expression dialect of tramlines (TL_118).

Message

<file>:<line>: error[TL_118]: `<key>` is not a valid regex: <reason>
<file>:<line>: error[TL_118]: type `<name>`: not a valid regex: <reason>
<file>:<line>: error[TL_118]: template `<template>` does not compile: <reason>

Cause

The command reads each regular expression in the Rust dialect. That dialect has no lookaround, such as (?=…) or (?<!…), and no backreference, such as \1. A pattern, a select-pattern, a source-pattern, an entry of prohibited-patterns, or a type doesn’t compile if it uses either of these or isn’t a valid regular expression at all. The <reason> comes from the regular expression library. For a template or a pattern of a format, the message starts with format `<format>`: , and for a variant, with format `<format>`: variant `<variant>`: .

Fix

Change the schema. Correct the syntax that the <reason> names. Rewrite lookaround or a backreference without it: a word boundary \b or a character class often does the same work.

Example

This schema bans TODO with a lookaround:

note.yaml

line-limit: 0
prohibited-patterns: [{pattern: '(?<![A-Za-z])TODO', message: 'A note contains no TODO.'}]
sections:
  - heading: Note
    level: 1
    blocks: []

note.md

# Note
$ tramlines validate --schema note.yaml note.md
note.yaml:2: error[TL_118]: `pattern` is not a valid regex: look-around, including look-ahead and look-behind, is not supported
1 error, 0 warnings
[exit 1]

Use a word boundary instead:

note.yaml

line-limit: 0
prohibited-patterns: [{pattern: '\bTODO', message: 'A note contains no TODO.'}]
sections:
  - heading: Note
    level: 1
    blocks: []
$ tramlines validate --schema note.yaml note.md
0 errors, 0 warnings