A YAML file can be wrong in two ways. It can break the syntax, so that no reader can say what it means. Or it can be valid and still mean something other than the writer thought, because the reader decides a plain value’s type from how it looks and readers disagree. This page covers both.
Syntax errors
The file viewer on this site reads the whole stream with a YAML 1.2 reader and reports
each error with its line and column. After an error the reader gives up on that
document and carries on at the next --- or ... line, so one
mistake does not hide the documents after it. These are the errors, grouped by what went
wrong.
| What went wrong | Example | Why it is an error |
|---|---|---|
| A line indented too far | a: 1 then ␣␣b: 2 | The second line is deeper than the mapping above it, but there is no key for it to belong to. |
| A second mapping on a key’s line | a: b: c | A block mapping cannot start after key: on the same line. Put it on the next line, indented, or use {b: c}. |
| A key over more than one line | a then b: c (as a key) | A key written without ? must be on one line. |
| No colon after a key | a: 1 then b | A line in a block mapping must be an entry, key: value. |
| A sequence entry in a mapping | a: 1 then - b | A - entry cannot be mixed into a mapping at the same level. |
| A tab as indentation | a: then tab b: c | Indentation is spaces only. A tab is allowed between tokens, never to indent. |
| A flow collection never closed | [a, b | The file ends, or a document marker appears, before the ] or }. |
| A missing comma | ["a" b] | Entries in a flow collection are separated by commas. A comma with no entry before it is also an error. |
| A quoted scalar never closed | a: "b | The closing quote is missing. |
| An unknown escape | "\q" | Only the escapes in the table are allowed after a backslash, and \x, \u and \U need two, four and eight hexadecimal digits. |
| Content after a flow node | [a] b | Nothing but a comment can follow a complete flow collection or quoted scalar on its line. |
| An alias with no anchor | a: *b | An anchor must be written before an alias that uses it, in the same document. |
| An alias with properties | &x *y | An alias cannot carry an anchor or a tag of its own. |
| Two anchors or two tags | &a &b c | A node has at most one of each. |
| A tag handle not declared | !e!x y | Named handles come from a %TAG directive in the same document. |
| An unclosed verbatim tag | !<tag:x | The !<…> form must end with >. |
A directive with no --- | %YAML 1.2 then a: b | Directives must be followed by a --- line. A directive also needs a ... line in front of it if a document before it is still open. |
A bad %YAML or %TAG | %YAML 1 | %YAML takes one version such as 1.2, and a major version other than 1 is an error. %TAG takes a handle and a prefix, and each handle can be declared once. |
Content after ... | ... x | Only a comment can follow a document end marker on its line. |
| A document marker in the middle | a --- line inside [ ] or inside a quoted string | A line that starts with --- or ... followed by white space always ends the document. |
| A reserved indicator | a: @b | @ and the backtick cannot start a plain scalar. Quote the value. |
| A comma, bracket or brace in an anchor name, in YAML 1.2 | a: &a,b x | A 1.2 name ends at a flow indicator, so ,b is left over. In a 1.0 or 1.1 document a name is any run of non-space characters, and &a,b is allowed. |
| Two carets in a YAML 1.0 tag | !domain.tld,2002/^in^voice | In YAML 1.0 a ^ separates a tag’s prefix from its name, so a tag can have only one unescaped ^ (write a literal one as \^). The ^ tag prefix |
A YAML 1.0 tag that starts with ^ and has no prefix to use | !^customer at the top of a document | !^name stands for the nearest ancestor’s prefix plus the name, so some ancestor’s tag must have set a prefix with !prefix^name. |
A YAML 1.0 stream that starts with a scalar and no --- line | hello, then a document that declares %YAML:1.0 | In 1.0 the first document may leave out its --- line only if it is a mapping or a sequence. |
| A comment with no space before it | "a"# c | A # starts a comment only at the start of a line or after white space. YAML 1.2 forbids the tight form and libyaml accepts it, so some tools read such a file. |
| A block scalar header followed by text | a: |x | After | or > and its chomping and indentation indicators, only a comment may follow. The indentation indicator is 1 to 9, never 0. |
| A more indented blank line | blank line of 6 spaces, then text at 4 | With no indentation indicator, a block scalar’s indentation is set by its first line with text, and a blank line before it cannot be indented further. |
| A line under-indented in a flow collection or quoted scalar | k: [a, then b] at column 0 | Continuation lines of a flow collection or quoted scalar must be indented at least as far as the block node that holds them requires. libyaml accepts less, so some tools read such a file. |
| A control character | a byte 0x01 in the text | Only tab, line feed and carriage return are allowed below U+0020. U+007F, the C1 controls U+0080 to U+009F (except U+0085) and U+FFFE and U+FFFF are also not allowed. Use an escape in a double-quoted scalar. |
Two limits are the viewer’s own, not the language’s: nesting deeper than 400 levels, and more than 8 million nodes. The viewer reports them and stops reading that document.
Problems that are not errors
These break a rule of the specification or are probably a mistake, but every reader can still say what the file means. The viewer lists them as notes, not errors.
- A repeated key in one mapping. The specification says keys must be
unique, and most readers keep the last value. A reader that checks (some do) refuses
the file. The viewer counts two keys as the same when their type and value match, however
they are written:
1and0x1,1.0and1.00,~andnull, and in a 1.1 documentyesandtrue.1and"1"differ. See Reading YAML in the explorer. - A tag that does not fit its node, such as
!!int abcor!!seqon a mapping, a!!yamlthat is not!,&or*, a!!tag that is not in the YAML tag repository, or a malformedtag:URI, is reported as a “Tag check” note on the same page. - A key longer than 1024 characters, written without
?. The specification limits implicit keys to 1024 characters, but most readers take longer ones. - An unknown directive, such as
%FOO. Readers ignore directives they do not know and should warn. - A version newer than 1.2, such as
%YAML 1.3. A 1.2 reader reads it as 1.2 and should warn. - Several documents without
...are fine: a---line also ends the document before it.
Valid, but not what you meant
A plain scalar has no type written on it. The reader decides from its text, using the
schema, and YAML 1.1 and 1.2 give
different answers for several common values. A file with no %YAML
directive is read by each tool as that tool’s version: PyYAML and libyaml follow most
of 1.1, and newer libraries follow 1.2.
| Written | YAML 1.1 | YAML 1.2 (core schema) |
|---|---|---|
no, NO, off | false (the “Norway problem”: the country code NO becomes false) | The string |
yes, on | true | The string |
y, n | Booleans in the type repository (many readers leave them as strings) | The string |
010 | Octal: the integer 8 | Decimal: the integer 10 |
0o10 | The string | Octal: the integer 8 |
0b101 | Binary: the integer 5 | The string |
1_000 | The integer 1000 | The string |
12:30:00 | Base 60: the integer 45000 | The string |
1e3 | The string (a 1.1 float needs a dot and a signed exponent) | A float, 1000 |
2001-12-14 | A timestamp | The string (the core schema has no timestamps) |
~, null, an empty value | Null | Null |
1.10 | The float 1.1 | The float 1.1 |
The last row is the classic version-number trap: a version written as
python: 3.10 is the float 3.1 in every YAML version. Quote it:
python: "3.10".
countries:
- GB
- NO # false in YAML 1.1
- "NO" # a string in every version
mode: 0755 # octal 493 in 1.1, decimal 755 in 1.2
port: 22:22 # 1.1 reads a base 60 number, 1.2 a string
version: 3.10 # the float 3.1 in both
tag: !!str 3.10 # the string 3.10
Other mistakes that are valid YAML:
key:valuewith no space is one plain scalar, not a pair. A colon starts a value only when white space follows it (or, in a flow collection, a flow indicator).- A plain scalar that starts with
*is an alias,&an anchor,!a tag,%an error,|and>a block scalar. Quote these values. - A value with
:or#in it is cut at that point. Quote it. - An empty value is null, not an empty string. Write
key: ""for the string. - A block scalar keeps its text exactly, so a missing
-or+after|changes the final line break. See chomping. - An alias reuses the same node, so changing the anchored value in a program that loads it into shared objects changes every alias too.
- A merge key
<<copies the entries of another mapping. It belongs to YAML 1.1’s type repository and is not in the 1.2 specification, but most libraries still support it. See merge keys.
Specification
The syntax errors are the cases where YAML 1.2.2’s productions in chapters 5 to 9 do not match. Section 3.2.1.3 describes the problem of duplicate keys, and the 1.1 type repository is at yaml.org/type. The yaml-test-suite lists about 400 inputs with the expected result for each, and the viewer’s reader gives the expected result for all of them.