Skip to content

YAML error

“error converting YAML to JSON”

kubectl does not parse YAML directly. It converts each document to JSON first, and this wrapper means that conversion failed because the YAML is malformed. The real error is the part after “yaml: line N:”, and N counts from the start of that document, not from the top of the file.

By yamltojsonfree · Published · Updated

What the parser is telling you

Kubernetes tools read a manifest with a decoder that splits the file at each ---, converts one document at a time to JSON with the sigs.k8s.io/yaml library, and only then maps the JSON onto a Deployment or a Service. A syntax error stops the first step, so you get “error converting YAML to JSON” followed by go-yaml’s message. Nothing about your Kubernetes object has been checked yet.

Because each document is converted on its own, the line number is relative to the document. In a file with a Service followed by a Deployment, an error on the Deployment’s eleventh line is reported as line 10, not as line 19. Helm adds a second offset: it reports lines in the rendered template, which can differ from the source once include, range and toYaml have expanded.

Two other kubectl messages look similar but mean different things. “error validating data” means the YAML parsed and the object failed schema validation, for example an unknown field. “error unmarshaling JSON” or “cannot unmarshal string into Go struct field” means the YAML parsed but a value has the wrong type, such as replicas: "3" with quotes.

Who prints this message

kubectl, Helm, kustomize and every tool built on the Kubernetes YAML libraries print this wrapper. The text after “yaml: line N:” comes from go-yaml and is the actual error.

The causes, with fixes

Broken YAML on the left, the corrected form on the right. The fix under each pair is the one that applies to that cause.

Find the document, then the line

The manifest below fails on file line 19, the eleventh line of the second document, but kubectl reports yaml: line 10: did not find expected '-' indicator: image sits one space left of name, so it belongs neither to the list item nor to the list.

Broken

apiVersion: v1
kind: Service
metadata:
  name: api
spec:
  ports:
    - port: 80
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: api
spec:
  replicas: 1
  template:
    spec:
      containers:
        - name: api
         image: nginx

Fixed

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: api
spec:
  replicas: 1
  template:
    spec:
      containers:
        - name: api
          image: nginx

Fix: Count lines from the first line after the previous ---, and expect the number to be off by one.

Read the inner message, then its own page

The text after “yaml: line N:” is one of a handful of go-yaml messages, each explained on this site: mapping values are not allowed in this context for a colon inside a value or a line indented too deep; did not find expected key for a key at a column that belongs to no block, or a dash where a key was expected; could not find expected ':' for a line without a colon; found character that cannot start any token for a tab used as indentation; control characters are not allowed for escape codes in the file; and did not find expected '-' indicator for a key wedged between a list’s dash and its items, as above.

Broken

# what kubectl prints
error: error parsing deploy.yaml:
  error converting YAML to JSON:
  yaml: line 10: did not find expected key

Fixed

# how to read it
# file:     deploy.yaml
# document: the one after the last ---
# line:     10 or 11 of that document
# problem:  did not find expected key

Fix: This pair is the message and its reading, not YAML to convert.

Helm: the line is in the rendered output

A template that renders to an empty value, or an include without nindent, produces YAML that is only wrong after rendering.

Broken

env:
  {{- include "app.env" . }}

Fixed

env:
  {{- include "app.env" . | nindent 2 }}

Fix: Run helm template . --debug to see the rendered manifest and count lines there. helm lint catches most of these before install.

Find it fast

  1. 1.Reproduce without touching the cluster: kubectl apply --dry-run=client -f file.yaml.
  2. 2.Split the file at --- and find the document with the reported line; the number counts from the line after the separator and may be one lower than you count.
  3. 3.Paste that document into the YAML validator on this site. It reads the whole input, marks the exact line and, for unclosed brackets and quotes, names the line where the delimiter was opened.
  4. 4.Once the YAML parses, an “error validating data” message is about the object’s fields, not its syntax; check the field names with kubectl explain.

How the message reads in each tool

ParserMessage
kubectl, kustomizeerror: error parsing file.yaml: error converting YAML to JSON: yaml: line N: ...
HelmError: YAML parse error on chart/templates/x.yaml: error converting YAML to JSON: yaml: line N: ...
kubectl, schema stageerror validating data: ValidationError(Deployment.spec): unknown field ...
kubectl, type stageerror unmarshaling JSON: while decoding JSON: json: cannot unmarshal string into Go struct field ...

Frequently asked questions

kubectl says line 12, but line 12 of my file is fine. Why?

kubectl splits the file at each --- and converts one document at a time, so the number is relative to the document that failed, not the file. Count from the first line after the previous separator. The number is also often one lower than the line you would count in an editor, so check that line and the one below it.

Is “error converting YAML to JSON” a Kubernetes problem or a YAML problem?

A YAML problem. The conversion happens before kubectl looks at what kind of object the file describes, so the manifest has a syntax error and would fail in any YAML parser. Problems with field names appear as “error validating data”, and wrong value types appear as “cannot unmarshal”.

Why does Helm report a line that does not exist in my template?

Helm parses the rendered output, not the template source. Lines added or removed by include, range, toYaml or an expression that renders empty shift the numbering. Use helm template with --debug to see the rendered YAML and find the line there, then trace it back to the template.

Related errors

All six underlying mistakes, ordered by cause rather than by message, are in the guide Common YAML errors and how to fix them. Every one of them is caught with the exact line and a suggested fix by the free tools below; nothing is uploaded.