Skip to content
🎉 Launch sale:50% off everything over $22 — automatically applied at checkout· ends Aug 2Shop the sale →
DevOps AI ToolKit
Newsletter
All guides
AI for Automation By James Joyner IV · · 7 min read Last reviewed Jul 2026

jq Error: 'Cannot iterate over null (null)' — Cause, Fix, and Troubleshooting Guide

Quick answer

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
Free toolkit

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 null is a path bug far more often than an empty data bug — inspect keys before assuming the API changed.
  • jq returns null for 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[]') — check type when unsure.
Free download · 368-page PDF

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?

Free download · 368-page PDF

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.