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.

Enable JavaScript to customise; default output below.

A config file, a workflow, a docker-compose file. Comments are read and not preserved, because they are not part of the data.

Indent with

Spaces either way. Tabs are forbidden in YAML indentation, which is why they are not an option.

Live preview formatted.yml
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.

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:value with 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: no is the string “no” in YAML 1.2 and was false in YAML 1.1, so the same file means two things depending on which library reads it.
  • port: 08080 was 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

  1. Paste the YAML.
  2. Read the findings.
  3. 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?
It validates and reports, which is most of what a linter does for one file. It does not check style rules such as line length or key order, and it is not a substitute for yamllint in CI. It is the thing to paste a file into when CI has failed and the message is unclear.
Why did my anchors disappear?
They did not: they are reported as an error and left as text. Expanding anchors changes the file’s meaning in ways you should choose deliberately, so the tool refuses rather than guessing. Write the value out, or format that file with a library that supports them.
Can I convert this to JSON?
Not here yet. The JSON to YAML converter on this site goes the other way. YAML is a superset of JSON, so any JSON you have is already valid YAML and can be pasted straight in.
Should I quote all my strings?
It is defensible: quoted strings are immune to every version difference and every surprise resolution, at the cost of a noisier file. The option is there. The middle road that most projects take is to quote only the values that could be read as something else, which is what the default does.
Does it handle multiple documents in one file?
It parses and formats the first, and says how many it found. A multi-document stream is usually several files that want separating, and the ones after the first are passed through unformatted rather than being quietly merged.
Weekly drops

New tools, when there are new tools

One email when something worth using ships. No schedule to fill, so no filler.

Your address goes nowhere else, and one click unsubscribes.