How to use the YAML Validator and Linter

  1. Paste the YAML, open a file, or load one of the examples.
  2. Leave the file type on Auto-detect, or pick Kubernetes, Docker Compose, GitHub Actions or Ansible.
  3. Fix syntax errors first, at the line and column shown.
  4. Work down the findings; each one names the line and gives the text to write.

What a YAML validator checks

A YAML validator first parses the file against the YAML 1.2 specification and reports anything that stops a parser, such as a tab used for indentation or a missing colon, with its line and column. A useful validator then goes further, because a file that parses can still be wrong: a duplicate key that silently overwrites another, a no that one tool reads as false, or a Deployment whose selector does not match its pods.

This page does three passes: syntax, lint, and checks for the file type it detects.

The lint checks

FindingWhy it matters
Duplicate keyYAML forbids it, but most parsers keep the last value and drop the first without a word
Tab in indentationYAML allows only spaces; tools reject the file or read a different structure
Value read differently by YAML 1.1yes, no, on, off, 0755, 22:22 change type between parsers (the "Norway problem")
Key that YAML 1.1 reads as a booleanon: becomes true: in PyYAML and other YAML 1.1 tools
Trailing whitespaceInvisible, noisy in diffs, and part of the value inside block scalars
Inconsistent indentationMixed 2- and 4-space levels make it easy to put a key at the wrong depth
Lines over 120 charactersHard to review; information only
No --- at the startOptional; yamllint's default rule asks for it; information only

The file-type checks

These are hand-written checks for the mistakes that come up most, not a full JSON Schema validation of each format, so a file can pass here and still be refused for a field this page does not know. The detected type is shown above the findings, and you can force a type.

  • Kubernetes: apiVersion, kind and metadata.name present and valid; API versions removed from current clusters (extensions/v1beta1, batch/v1beta1 CronJob and others); Deployment, StatefulSet and DaemonSet spec.selector matching the template's labels; every container with a name and an image; containerPort a number, not a quoted string; env values strings; resource quantities such as 256Mi and 500m (and the classic memory: 512m, which is half a byte).
  • Docker Compose: services present, each with image or build; unknown keys and typos such as enviroment; port mappings in host:container form and quoted, because 22:22 is the base-60 number 1342 to a YAML 1.1 parser; named volumes and networks declared; depends_on naming real services, with service_healthy only for services that have a healthcheck; the obsolete top-level version.
  • GitHub Actions: on and jobs present; every job with runs-on and steps; each step with uses or run but not both; actions pinned with @; needs naming real jobs; and ${{ github.event.issue.title }} or similar inside run, which lets whoever opens an issue run shell commands.
  • Ansible: a playbook is a list of plays; each play has hosts; unknown play keywords such as handler (Ansible stops on them); tasks with no module or two modules (the error "conflicting action statements", usually a module's options not indented under it); the removed sudo keyword.

Worked example: a Compose file

services:
  web:
    build: .
    ports:
      - 22:22            # YAML 1.1 reads 1342
    enviroment:          # typo: Compose rejects the key
      - NODE_ENV=production

The validator reports the unquoted port, suggests - "22:22", and names environment as the key that was meant. To check the same on a server, docker compose config parses the file with Compose's own rules and prints the result, and kubectl apply --dry-run=server -f deploy.yaml asks the cluster to validate a manifest without applying it.

Fixing the most common errors

  • "Tabs are not allowed as indentation": set your editor to insert spaces in YAML files.
  • "Nested mappings are not allowed in compact mappings": a value contains : . Quote it.
  • "Map keys must be unique": merge the two entries; only one survives otherwise.
  • "Implicit keys need to be on a single line": look one line up for an unclosed quote.

With Shipown

Shipown deploys Dockerfile and Compose projects to your own Linux server and shows the ports, environment values and volumes before it runs. A Compose file that passes here, and docker compose config on the server, is one that will not fail the deploy on a typo. The Docker module docs cover the rest of the workflow.

Frequently asked questions

Is this a full Kubernetes or Compose schema validator?

No. The file-type checks are hand-written checks for the most common mistakes. For a complete check, run kubectl apply --dry-run=server or docker compose config as well.

Why is "on:" in my GitHub workflow flagged?

It is information only. GitHub reads it correctly, but YAML 1.1 parsers such as PyYAML turn the key into the boolean true, which confuses other tools that read the workflow.

What is the Norway problem?

In YAML 1.1 the unquoted values yes, no, on, off, y and n are booleans, so the country code NO becomes false. YAML 1.2 reads them as strings. Quoting the value makes every parser agree.

Why does memory: 512m fail in Kubernetes?

Lowercase m means milli, so 512m is 0.512 bytes. Write 512Mi for mebibytes or 512M for megabytes.

Which file type does auto-detect pick?

apiVersion and kind mean Kubernetes, jobs with on mean GitHub Actions, a services mapping means Compose, and a list of plays with hosts means an Ansible playbook. The page says which it used.

Is my YAML uploaded?

No. Parsing and every check run in your browser.