YAML Formatter & Validator
Formats YAML and reports the quiet mistakes: key:value with no space, duplicate keys, tabs in indentation, and YAML 1.1 versus 1.2 values.
Lines in 14
Documents 1
Errors 0
Warnings 2
Findings
Line 4 warning: "no" is a string in YAML 1.2 and was a boolean in YAML 1.1. Older parsers, including some in CI, will read it as false. Quote it, or write true or false.
Line 5 warning: "08080" has a leading zero. In YAML 1.1 that made it octal, so 08 was an error and 0755 was 493; in 1.2 it is a string. Quote it if it is an identifier such as a phone number, a port written out or a zero-padded version.
No errors, but the warnings are worth reading. Each one is a value that
means one thing to a YAML 1.2 parser and something else to a YAML 1.1
one, and both are still in use: PyYAML defaults to 1.1, Go and
JavaScript libraries are mostly 1.2.
Formatting decisions made here: two spaces by default and never tabs,
since tabs are forbidden in YAML indentation; quotes only where the
value would otherwise change type; and block scalars for any string with
a newline in it, which is more readable than an escaped one-liner.
Comments are not preserved. A parser that reads YAML into a value and
writes it back out loses them, because comments are not part of the
data. If the comments matter, format by hand or use a round-tripping
library such as ruamel.yaml.
----------------------------------------
name: bucketwp
version: 2.4
debug: "no"
port: "08080"
paths:
root: /var/www
cache: /var/cache
features:
- sync
- name: webhooks
url: https://swiftplugins.pro/hook
retries: 3
notes: |-
first line
second line
Output is valid and updates as you type.
Fix the highlighted fields to update the output.
YAML’s failure modes are quiet. A file with any of these in it loads without complaint and means something other than what you wrote:
key:valuewith no space after the colon is one string, not a key and a value.- A duplicate key is invalid YAML, and most parsers keep the last one silently.
- A tab in the indentation is forbidden, and your editor put it there without showing you.
debug: nois the string “no” in YAML 1.2 and wasfalsein YAML 1.1, so the same file means two things depending on which library reads it.port: 08080was octal in 1.1 and is a string now.
So this formats the file, and it reports all of those with line numbers first.
How to use
- Paste the YAML.
- Read the findings.
- Copy the formatted output: two or four spaces, quotes only where a value needs them, block scalars for anything with newlines.
Example
A config file with two of the classic problems in it:
Lines in 14
Documents 1
Errors 0
Warnings 2
Findings
Line 4 warning: "no" is a string in YAML 1.2 and was a boolean in YAML 1.1. Older parsers, including some in CI, will read it as false. Quote it, or write true or false.
Line 5 warning: "08080" has a leading zero. In YAML 1.1 that made it octal, so 08 was an error and 0755 was 493; in 1.2 it is a string. Quote it if it is an identifier such as a phone number, a port written out or a zero-padded version.
and the formatted file:
name: bucketwp
version: 2.4
debug: "no"
port: "08080"
paths:
root: /var/www
cache: /var/cache
features:
- sync
- name: webhooks
url: https://swiftplugins.pro/hook
retries: 3
notes: |-
first line
second line
debug and port came back quoted, which is the fix for both warnings: quoted, they
are the same string under every version of the spec.
Pitfalls
key:value is not a mapping. It is the string key:value. YAML needs a space
after the colon, and nothing will tell you otherwise: the key you expected simply is
not there, and the error surfaces later as a missing setting.
Duplicate keys are invalid and usually silent. Two version keys in one mapping
is an error by the specification, and PyYAML, js-yaml and Go’s yaml all take the last
one without a word. A merged config file or a careless copy and paste is how it
happens.
Tabs are forbidden in indentation. Not discouraged: forbidden. An editor set to tabs will produce a file that no YAML parser will read, and the error message is usually unhelpful about why.
YAML 1.1 and 1.2 are both in use. PyYAML implements 1.1, which reads yes, no,
on and off as booleans and 12:30 as 750. Most JavaScript and Go libraries
implement 1.2, where all of those are strings. If a file is read by both, quote
anything ambiguous.
Indentation is significance, and two spaces is convention rather than law. Any consistent number works, and a sequence may be indented level with its parent key, which is why both of these are the same document:
features:
- sync
features:
- sync
Comments do not survive a round trip. A parser reads YAML into a value; comments are not part of the value. Anything that formats YAML by parsing and re-emitting loses them, this tool included. That is a reason to format by hand in a file where the comments are documentation.
A tab inside a string is fine. The rule is about indentation. Quoted strings can contain whatever they like.
Compatibility
Everything runs in the browser: nothing is uploaded and nothing is stored, which matters for a config file with hostnames or credentials in it.
The parser covers the subset that configuration files use: documents, block mappings and sequences, plain and quoted scalars, block scalars with chomping indicators, simple flow collections, comments, and the YAML 1.2 core schema for types. Anchors and aliases are reported rather than expanded, because a formatter that silently dropped an anchor would be worse than one that says it cannot handle it. Complex keys, tags and merge keys are outside that subset too.
Type resolution follows YAML 1.2, so yes is a string here. Where 1.1 would have
disagreed, the tool says so rather than picking a side quietly.
The output is what the parser understood. On a file with errors that is the most useful thing to look at: a value that has come out as a string or a key that has landed one level too deep tells you where the mistake is faster than the error message does.
Frequently asked questions
Is this a YAML linter?
yamllint in CI. It is the thing to paste a file into when CI has failed and the
message is unclear.