Free online YAML syntax checker
YAML validator that catches the quiet mistakes
This YAML validator is free, with no signup and no daily limit. Drop in a manifest of up to 5 MB and it marks the first syntax error with the rule it broke, the line, the column and a pointer under the offending character. It then does the part a plain parser cannot, and lists the values that are perfectly legal YAML and still not what you meant — a duplicate key one loader keeps and another rejects, an unquoted no that becomes false, a version of 1.0 that becomes the number 1, a port mapping of 22:22 that becomes 1342. Structure is read as YAML 1.2, with every place a YAML 1.1 loader would disagree named separately.
- 100% free
- No signup
- Up to 5 MB
- Line and column
- 1.1 vs 1.2 traps
YAML 1.2 syntax check plus the 1.1 type traps that still bite
Paste YAML, drop a file, or press Ctrl+V anywhere on this page. The verdict updates as you type.
Syntax is one half of it — convert the document to JSON to see exactly which value each key resolved to.
How to validate a YAML file
Three steps: parse it, fix it, then find out what it actually says.
Paste the document
Drop a .yml or .yaml file on the box, type into it, or paste from anywhere on the page with Ctrl+V — ⌘V on macOS. Kubernetes manifests, Compose files, Ansible playbooks, GitHub Actions workflows and OpenAPI specs are all ordinary YAML, up to 5 MB. Two sample buttons load a file that parses but lies to you, and one that will not parse at all.
Fix the parse error first, if there is one
A structural failure is reported with its category, the line, the column and a marker sitting under the character where the parser gave up — a tab in the indentation, a key indented past its siblings, an unclosed quote, an alias with no anchor. YAML has no closing brackets to resynchronise on, so a parser reports the first thing it cannot reconcile and stops there.
Read the warnings on a document that parses
Below the verdict sit the values that are legal and surprising: a duplicate key that half the loaders silently drop, an unquoted no that becomes false under YAML 1.1, a version of 1.0 that comes back as the number 1, a file mode of 0755 read as octal, a port mapping of 22:22 read as base 60, and a hex colour eaten by the comment it accidentally started. Each says which loaders behave which way and what quoting fixes it.
Technical specifications
| Grammar handled | Block mappings and sequences, compact - key: value entries, sequences level with their parent key, flow collections across lines, quoted scalars across lines, literal and folded block scalars with chomping and indentation indicators, anchors, aliases, tags, directives and multi-document streams |
|---|---|
| Structural errors named | 18, among them a tab in the indentation, an over-indented key, a colon with no space, a missing space after a dash, an unclosed quote or flow collection, an alias with no anchor, and a second root node without a --- marker |
| Traps reported on a file that parses | Duplicate keys, yes/no/on/off booleans, y and n, floats such as 1.0, leading-zero octals, base-60 values such as 22:22, integers past 2^53, a # that ate the value, merge keys, unused anchors and a mixed indent width |
| Error report | The rule that was broken, where the parser gave up as a line and a column, the offending line reprinted with a marker beneath it, and what to change |
| Version behaviour | Structure parsed as YAML 1.2; every place a YAML 1.1 loader would resolve a value differently is listed separately |
| What it does not do | No schema validation: nothing here checks a document against a Kubernetes CRD, an OpenAPI schema or a JSON Schema, and no value is converted |
| Maximum document size | 5 MB (5,242,880 bytes) and 500 levels of nesting; a 5 MB manifest bundle is checked in about 0.2 seconds |
| Cost and processing | Free, no signup, no daily cap; the parser is JavaScript running in this browser tab and the file is never uploaded |
Frequently asked questions
Why does YAML treat no as false?
Because YAML 1.1 defined the boolean type as ten spellings — yes, no, on, off and true, false, each in lower, title and upper case — and the loaders most people use still implement 1.1. The consequence has a name, the Norway problem: a country list written as country codes turns NO into the boolean false while every other code stays a string, so Norway vanishes from the data with no error anywhere. YAML 1.2 fixed it by shrinking the core schema to true and false alone, but PyYAML, Ruby's Psych and go-yaml v2 predate that decision and js-yaml 4 and go-yaml v3 do not, which means the same file can produce two different values depending on what reads it. Quoting the value settles it everywhere.
Why can I not use tabs to indent YAML?
Because a tab has no defined width, and in YAML the width is the structure. The specification bans tabs from indentation outright — it is one of the very few flat prohibitions in the format — precisely because a parser deciding whether a line is a child or a sibling has to count columns, and it cannot count a character whose size depends on an editor setting. Tabs are perfectly legal inside a value and inside a block scalar; it is only the whitespace that marks a block off that must be spaces. The usual fix is to set your editor to insert spaces for YAML files rather than to convert them by hand.
Are duplicate keys an error in YAML?
By the specification yes, in practice almost never. YAML 1.2 states that the keys of a mapping must be unique and calls a repeat an error, yet PyYAML, go-yaml, Psych and js-yaml in its default mode all take the last occurrence and discard the earlier ones without a word. The Kubernetes API server rejects the document, and js-yaml in strict mode does too, so the same manifest can be accepted by your local tooling and refused by the cluster. It matters most in files assembled by templating, where two branches each contribute a resources: block and only one of them survives.
Why did my version number 1.0 come back as 1?
Because an unquoted 1.0 is a float, and a float has no memory of the zero you typed. Load it and re-serialise it and you get 1, which is how docker-compose files acquired the famous "version: 3.0 became 3" complaint. The same shape catches API revisions, firmware numbers and anything measured in tenths. Note the asymmetry that makes it hard to spot: 1.2.3 has two dots and stays a string, so most of your version fields survive and the one with a single dot does not. Quote every version number and the problem disappears.
Why is my hex colour empty after loading?
Because a # that follows a space opens a comment, so colour: #4c1d95 sets colour to null and throws the rest of the line away. There is no special case for values that look like something else — the parser sees whitespace, then a hash, and stops reading. The same rule eats a fragment identifier in an unquoted URL and an issue reference such as fixes #214. Quote anything that starts with a hash. A # with no space in front of it, as in tag: v1#build, is just a character in the value.
What is the difference between YAML 1.1 and 1.2, and which one is my loader?
YAML 1.2 aligned the language with JSON and moved almost all of the old type magic out of the default behaviour; YAML 1.1 resolved yes and no to booleans, numbers with a leading zero to octal, and colon-separated digits to base 60. Which one you get depends entirely on the library: PyYAML implements 1.1 and has done for twenty years, Ruby Psych follows 1.1 for booleans, go-yaml v2 is 1.1 while v3 is 1.2 core, and js-yaml has been 1.2 since version 4. This page parses the structure as 1.2 and then tells you every place where a 1.1 loader would disagree, because a config file usually gets read by more than one of them.
What does “mapping values are not allowed in this context” mean?
It means a colon turned up inside something the parser had already decided was a plain scalar. The two usual causes are a value that runs onto the next line — because a plain scalar folds across lines, and once it does a second key: on the following line has nowhere to live — and a missing space after a colon higher up, as in port:8080, which makes the whole line one scalar that then swallows the line below it. Both are reported here with the line that started the scalar as well as the line the parser choked on, since the first is where the fix goes.
About YAML, and why valid is not the same as correct
YAML puts structure in the whitespace, which buys readability and costs you every safeguard a bracket would have provided. There is no closing token to resynchronise on, so a parser that loses the thread cannot recover the way a JSON parser does at the next }; it reports the first line it cannot reconcile and stops. That is why a YAML error so often points a line or two below the real mistake — the file stayed grammatical right up until the moment it could not, and the fix usually belongs to the key above the one being complained about. It is also why the specification bans tabs from indentation outright: a character with no defined width cannot carry meaning that is measured in columns.
The deeper problem is not syntax at all. YAML 1.1, published in 2005, shipped a generous type resolver: yes and no were booleans, a leading zero meant octal, and colon-separated digits meant base 60 so that times and angles could be written naturally. YAML 1.2 arrived in 2009, aligned the language with JSON and cut the default schema back to true and false — but the libraries did not follow in step. PyYAML is still a 1.1 implementation, go-yaml v2 is and v3 is not, Psych keeps the old booleans, and js-yaml moved to 1.2 in version 4. So a file can be read by CI in Python and by a tool in Go and quietly mean two different things, with no error raised on either side. Those are the warnings on this page: not complaints about your syntax, but a list of the places where two conforming loaders disagree about your data.
Duplicate keys sit in the same category. The specification says the keys of a mapping must be unique and calls a repeat an error; almost every loader keeps the last and drops the first without a word, while the Kubernetes API server refuses the document outright. A templated manifest that emits resources: from two branches therefore works locally and fails on apply, or worse, works everywhere and silently uses half the configuration. Once the structure is sound, the fastest way to confirm what a document actually contains is to look at the values rather than the text: convert it to JSON and every resolution is spelled out, quotes and all. If the indentation is what needs work, the YAML formatter normalises it to a single width.
Where your YAML is checked
The parser ships with the page and runs on your own machine, so the document is never uploaded, logged or stored anywhere. Manifests and playbooks tend to carry hostnames, bucket names and the shape of an internal network even when the secrets are elsewhere, which is the practical reason this check runs on your machine rather than on a server.