Skip to content

All tools (47)

JSON 6
Time & Date 4
Encoding & Decoding 5
Generators 4
Text & Data 5
Logs & Debugging 2
Config & Infra 4
Security & Hashing 5
Color & Design 5
Numbers & Bits 3
Web & Markup 4

Nothing leaves the cave.

Nothing you paste ever leaves your device. There is no server to send it to.

How you can check →
DevToolsCave Everyday developer tools

    YAML Validator

    Check YAML syntax in your browser, then see how PyYAML, Kubernetes and Spring Boot's real parsers would read every value.

    Lint

    Paste YAML to check it

    Worked example: a valid Docker Compose file
    services:
      api:
        image: registry.example.com/cave-api:2026.09.12
        ports:
          - "8080:8080"
        environment:
          REGION: no
          LOG_LEVEL: debug
        restart: unless-stopped
    
      cache:
        image: redis:7
        restart: unless-stopped
    

    ⚠ Valid YAML, read differently by 4 reader(s) — the REGION: no line reads as the boolean false under PyYAML, SnakeYAML and go-yaml v2. 1 document, 11 keys.

    What "valid" means: three questions, not one

    A validator that only says "valid" or "invalid" hides the thing worth knowing. This tool keeps three questions separate and never blurs them together. Level 1 (syntax) asks whether the text can be parsed as YAML 1.2.2 at all — checked against the language spec, and the only question with a strict ✗/✓ answer. Level 2 (loading) asks whether a specific library will reject or silently change the file when it loads it — a duplicate key is valid syntax, but PyYAML keeps the last value without a word while js-yaml throws outright. Level 3 (reading) asks what a real parser resolves a given value to — a bare no is text under YAML 1.2 core and the boolean false under PyYAML, SnakeYAML and go-yaml v2. A file can be perfectly valid at Level 1 and still surprise you at Level 2 or 3, and the headline verdict says exactly which is true, rather than collapsing all three into one word.

    The most common YAML errors

    Every syntax error code this tool reports, in plain words
    What's wrongExampleWhat PyYAML says for the same mistake
    This line is indented differently from the lines next to it a: b: 1 c: 2 mapping values are not allowed here
    A ":" inside this value looks like the start of another key k: a: b mapping values are not allowed here
    There's a tab character in this line's indentation a: b: 1 found character '\t' that cannot start any token
    This double-quoted value never closes k: "abc while scanning a quoted scalar, found unexpected end of stream
    This single-quoted value never closes k: 'abc while scanning a quoted scalar, found unexpected end of stream
    This { or [ never closes k: [1, 2 while parsing a flow node, expected the node content, but found end of stream
    Expected a comma between items here k: [1 2] missed comma between flow collection entries
    A plain value can't start with this character k: @x found character '@' that cannot start any token
    This line wasn't read as part of the document a: 1 b: 2 error 1:4 (unexpected content after a complete value)
    This alias refers to an anchor that doesn't exist a: *x BAD_ALIAS
    An alias can't also carry a tag or another anchor a: &x 1 b: !!str *x ALIAS_PROPS
    This isn't a valid escape sequence k: "\q" found unknown escape character
    A directive needs a --- after it %YAML 1.2 a: 1 MISSING_CHAR (directives end mark expected)
    A list item and a mapping key can't sit at the same indent - a b: 1 end of the stream or a document separator is expected
    A line inside this block scalar is indented less than the block itself k: | x y BAD_INDENT
    This implicit key is too long — KEY_OVER_1024_CHARS

    Each error here shows the exact line and column, an excerpt with a caret pointing at the fault, a plain-English explanation of why YAML refuses to guess, and — in a "What other parsers say" disclosure — the real message PyYAML, go-yaml and js-yaml print for the same mistake, so a search for that exact error text lands on an answer.

    Valid, but read differently

    Six real YAML readers, by spec
    ReaderSpecUsed by
    YAML 1.2 core 1.2 js-yaml 4, yaml 2 (eemeli/yaml), ruamel.yaml, YamlDotNet, libfyaml, yq (Go, mikefarah)
    PyYAML 1.1 PyYAML, Ansible, Home Assistant, pre-commit, mkdocs
    SnakeYAML 1.1 SnakeYAML, Spring Boot, Jenkins (Groovy pipeline YAML)
    go-yaml v2 (Kubernetes / Helm) 1.1 Kubernetes (sigs.k8s.io/yaml, historically), Helm, kubectl, kustomize
    go-yaml v3 1.2-ish Compose v2 (compose-spec reference impl), many Go CLIs
    Psych (Ruby) 1.1 Ruby (Psych is the stdlib YAML library), Rails, GitLab CI

    A bare no, an unquoted on: key, a leading-zero number like 0777, or a two-digit string like 08 all mean different things to different real parsers — some read 1e3 as the float 1000, PyYAML reads it as the literal text "1e3" because its float grammar requires a signed exponent. The Readers tab shows exactly which of your file's values are ambiguous this way, under every profile at once or narrowed to the one your deployment target actually uses.

    Duplicate keys: the silent case is the dangerous one

    The YAML spec is unambiguous: keys in a mapping must be unique. Real parsers disagree on what to do about a file that breaks that rule. js-yaml and the yaml npm package both throw an error immediately. PyYAML's safe_load — the parser behind Ansible, pre-commit and Home Assistant — keeps the last value and raises no warning at all. That means a config block accidentally pasted twice doesn't fail loudly; it silently overwrites itself, and the file "works" right up until the missing half is the half that mattered. This tool always calls out a duplicate key, whichever reader you're checking against, because the spec says it is wrong even where a library lets it through.

    Lint rules, stated plainly

    Lint is a different, optional layer — a trailing space never turns a ✓ into a ⚠, and lint is off by default so a first-time visitor pasting a working file isn't greeted by a wall of style warnings. When turned on, this tool uses yamllint's own rule names and default settings, for 14 of its 23 rules — the rest need a positioned token stream this engine doesn't build yet, and the page states that honestly rather than rounding up.

    • house/version-number
    • house/colon-without-space
    • house/dash-without-space
    • house/hash-without-space
    • house/leading-zero
    • house/norway

    The checks above are this tool's own opinion, never given a yamllint name, so they can never be mistaken for one of yamllint's own rules.

    Checking YAML from the terminal

    • yamllint file.yaml — the reference implementation for style; PyYAML underneath, so it inherits PyYAML's YAML 1.1 value resolution as well as its own lint rules.
    • python -c "import sys, yaml; yaml.safe_load(open(sys.argv[1]))" — the exact parser Ansible, Home Assistant and pre-commit use; a duplicate key here loads silently.
    • yq '.' file.yaml — mikefarah's yq is a YAML 1.2-family reader, so a bare no stays text, unlike Ansible's own PyYAML.
    • kubectl apply --dry-run=client -f file.yaml — validates against the Kubernetes API schema (this tool does not), using go-yaml under the hood for the YAML layer itself.

    Common use cases

    • Checking a Docker Compose or Kubernetes manifest is syntactically valid before a deploy
    • Finding the exact line a hand-edited config file broke on, with a caret pointing at it
    • Confirming a bare no, yes, on or off reads the way your specific deployment target reads it
    • Catching a silently duplicated key before it silently overwrites half a config block
    • Getting yamllint-style findings without installing Python or yamllint locally

    Frequently asked questions

    Is my YAML uploaded anywhere?
    No. Parsing, the per-reader resolution and the lint pass all run in this tab's own JavaScript. Nothing is sent to a server, logged, or stored — open the Network tab before you paste to confirm it for yourself.
    Which YAML version does it check?
    Syntax is checked against YAML 1.2.2, the current spec. Values are checked against six real readers spanning both YAML 1.1 (PyYAML, SnakeYAML, go-yaml v2) and YAML 1.2 (js-yaml/yaml, go-yaml v3, Psych's own mix) — because the honest answer to "is this valid" is different from the honest answer to "how will my deployment target read it".
    Why does it say "valid" and still warn me about no?
    Because those are two different questions. Level 1 (syntax) asks whether the text parses as YAML at all — a bare no parses fine. Level 3 (reading) asks what a real parser resolves that text to, and PyYAML, SnakeYAML and go-yaml v2 all resolve a bare no to the boolean false, not the string "no". Both facts are true at once, so the verdict shows both rather than picking one and hiding the other.
    Is a duplicate key an error?
    The spec says yes — keys in a mapping must be unique. But not every parser enforces it: js-yaml and the yaml package both throw, while PyYAML's safe_load silently keeps the last value and says nothing at all. That silent case is the dangerous one, so this tool always calls it out even though the file "loads" in some readers.
    Does it validate Kubernetes, Docker Compose or GitHub Actions files?
    It checks syntax and how the specific parser that tool actually uses would read your values — and shows a badge naming which file type it detected and why. It does not check the tool's own schema (whether a Kubernetes field name is spelled right, or a Compose key is in the right place). That is a much larger, separate feature this tool does not claim yet.
    Why does it only show the first syntax error?
    Once one structural mistake breaks the parse, everything after it is usually a knock-on effect of that first mistake, not an independent error — real parsers routinely report three or four errors for one root cause. Showing the first one precisely, with its exact line and column, is more useful than a list where most entries are noise. Fix it and check again; later errors can be caused by this one.
    Is this the same as yamllint?
    It uses yamllint's own rule names and default settings for 14 of its 23 rules — stated plainly rather than implied. The remaining rules need a positioned token stream this engine doesn't build yet. Lint is off by default; turn it on with the Lint segment above the editor.