jq Error: 'Cannot iterate over null (null)' — Cause, Fix, and Troubleshooting Guide
Fix jq error: Cannot iterate over null (null) — a missing key, wrong path, empty API response, or wrong nesting feeds null into .[] iteration.
- #automation
- #troubleshooting
- #jq
Fixing errors like this? Get 500 free DevOps AI prompts
500 copy-paste AI prompts for the stack you actually run — one PDF, free.
Overview
jq raises Cannot iterate over null (null) when you ask it to iterate — with .[], [.foo[]], map(), or a pipe into an array operation — over a value that is null instead of an array or object. In jq, looking up a key that does not exist returns null (it does not error), and null cannot be iterated, so the failure surfaces one step later at the iteration.
$ curl -s https://api.example.com/v1/items | jq '.data[] | .id'
jq: error (at <stdin>:0): Cannot iterate over null (null)
The message is almost never about the data being genuinely empty — it is about a path mismatch. The key you indexed (.data) does not exist in the JSON (maybe it is .results, or the payload is nested differently, or the request returned an error object), so .data evaluated to null, and null[] is what jq refused to iterate. The exit status is non-zero (5), which fails the surrounding script.
Symptoms
jq: error (at <stdin>:N): Cannot iterate over null (null).- jq exits non-zero (5), breaking the pipeline or CI step.
- The raw JSON looks fine to the eye, but the specific path you indexed is absent.
- Works against one API response and fails against another (empty result, error body, or different schema).
- Intermittent: passes when data is present, fails when the list is empty or the endpoint returns an error object.
curl -s https://api.example.com/v1/items | jq '.data[]' >/dev/null; echo "exit: $?"
exit: 5
Common Root Causes
1. The key does not exist (typo or wrong name)
.data when the field is actually .results — the lookup returns null, then .[] fails.
curl -s https://api.example.com/v1/items | jq 'keys'
[
"results",
"page",
"total"
]
2. Wrong nesting level
The array is one level deeper (or shallower) than the expression assumes, e.g. .data.items[] vs .data[].
3. Empty or error API response
The endpoint returned {}, an error object like {"error":"not found"}, or nothing — so the expected array key is absent.
4. Iterating a value that is legitimately null for this record
An optional field (.tags[]) is null on some records and a list on others; the run fails the first time it hits a null.
5. Response is a JSON array at the top level, not an object
If the body is already [...], then .data is wrong — you want .[] directly.
6. HTTP error body captured instead of JSON
A 4xx/5xx returned HTML or a plain-text error that either fails to parse or lacks the key.
How to Diagnose
Step 1: Look at the actual shape before indexing
curl -s https://api.example.com/v1/items | jq 'type, keys?'
"object"
[
"results",
"page",
"total"
]
The top level is an object whose keys are results, page, total — there is no data, which is exactly why .data was null.
Step 2: Confirm the offending path is null
curl -s https://api.example.com/v1/items | jq '.data'
null
null here proves the path, not the data, is the problem.
Step 3: Capture the raw body in case it is not what you expect
curl -s -w '\nHTTP %{http_code}\n' https://api.example.com/v1/items | tail -5
{"error":"not found"}
HTTP 404
A 404 error object explains the missing array entirely.
Step 4: Check the top-level type (object vs array)
curl -s https://api.example.com/v1/items | jq 'if type=="array" then "top-level array" else "object" end'
Fixes
Use the correct path once you know the real key:
curl -s https://api.example.com/v1/items | jq '.results[] | .id'
Make the expression null-safe so an empty or missing list yields no output instead of an error. // supplies a default, and ? suppresses iteration errors:
# Default a missing/null value to an empty array
curl -s https://api.example.com/v1/items | jq '(.data // [])[] | .id'
# Or tolerate the error and emit nothing
curl -s https://api.example.com/v1/items | jq '.data[]? | .id'
Both approaches let a legitimately empty response pass cleanly:
echo '{}' | jq '(.data // [])[]'; echo "exit: $?"
exit: 0
Guard the HTTP status in the script so an error body never reaches jq:
resp=$(curl -s -w '\n%{http_code}' https://api.example.com/v1/items)
code=$(printf '%s' "$resp" | tail -1)
body=$(printf '%s' "$resp" | sed '$d')
[ "$code" = "200" ] || { echo "HTTP $code: $body" >&2; exit 1; }
printf '%s' "$body" | jq '.results[] | .id'
What to Watch Out For
Cannot iterate over nullis a path bug far more often than an empty data bug — inspectkeysbefore assuming the API changed.- jq returns
nullfor a missing key rather than erroring, so the failure appears one operation downstream at the iteration. .[]?and(.x // [])are the idiomatic guards, but do not sprinkle them everywhere — a silenced error can hide a genuinely broken response.- An HTTP 4xx/5xx body is still fed to jq unless you check the status first; a non-200 error object is a common trigger.
- Distinguish a top-level array (
jq '.[]') from an object with an array field (jq '.data[]') — checktypewhen unsure.
Related Guides
- yq: bad file / YAML mapping values are not allowed
- 429 Too Many Requests — downstream rate limit
- n8n node execution failed: ECONNRESET
Fixed it? Get 500 Automation & DevOps AI prompts — free
500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.
- 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
- Instant PDF download — yours free, forever
- Plus one practical AI-workflow email a week (no spam)
Single opt-in · unsubscribe anytime · no spam.
Did this fix your issue?
Get 500 Battle-Tested DevOps AI Prompts — Free
500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.
- 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
- Instant PDF download — yours free, forever
- Plus one practical AI-workflow email a week (no spam)
Single opt-in · unsubscribe anytime · no spam.