Desk Clarity

A field guide to everyday digital problems.

Developer tools / Practical guide

jq Exit Status with -e: The Last Value Is Not an All-Items Check

Build one explicit validation result when a shell command must approve every record.

By ON Lab3 min readSources checked November 10, 2026 (KST)

jq -e bases its success result on the last output value. A filter that emits false and then true can exit successfully. For an all-records gate, produce one aggregate boolean that expresses your validation policy.

Reproduce the boundary in a disposable fixture

Build one explicit validation result when a shell command must approve every record.

Use a new empty temporary directory for this fixture. The example creates only local test data. Commands marked with example.invalid do not identify a real service.

set +e
printf '%s\n' '[false,true]' | jq -e '.[]' > values.txt
status_last=$?
printf '%s\n' '[false,true]' | jq -e 'all(.[]; . == true)' > all.txt
status_all=$?
printf '%s\n' '[]' | jq -e '.[]' > empty.txt
status_empty=$?
set -e
test "$status_last" = 0
test "$status_all" = 1
test "$status_empty" = 4
printf 'last=%s all=%s empty=%s\n' "$status_last" "$status_all" "$status_empty"
printf '%s\n' '[]' | jq -e 'length > 0 and all(.[]; . == true)' > nonempty.txt && exit 1 || test $? = 1

Observed result

last=0 all=1 empty=4

What the result means

The first filter emits two values: false followed by true. Its status is zero because the final emitted value is true. The all expression emits one false result and exits with status one. Producing no result is another case, shown by an empty iterator returning status four under -e on the installed jq. Terminal output and shell status answer different questions, so inspect both when writing a validation step.

Choose the correction for your workflow

Write a filter that emits one boolean for the actual condition you want. For an array of records, validate the array shape first and then use an aggregate test such as all(.[]; .valid == true). Decide what an empty array means: an all test can be true for an empty set, so add a nonempty condition when no records must be considered failure. Test valid, invalid, mixed and empty fixtures before making the status a deployment or data-import gate. Preserve jq parser and execution errors rather than turning every nonzero status into the same business verdict.

Limits and the next check

The fixture checks jq 1.7.1 on the installed machine. Without -e, a successfully evaluated filter generally does not turn a false output into failure; syntax, usage and execution errors have their own statuses. In a shell pipeline, the status you observe can be from a different command unless you capture the correct stage or apply an intentional pipefail policy. This article handles jq output semantics; the existing Bash pipeline guide covers stage status. Do not use a multi-output filter as an all-records gate by accident.

Related: Compare the related workflow boundary.

This isolated example was executed on macOS on November 10, 2026 (KST). Available tools: node v26.5.0, git git version 2.39.3 (Apple Git-145), npm 11.17.0, jq jq-1.7.1-apple. Shell fixtures use Bash and repository-path identity uses Python 3. This checks the illustrated contract, not your project, host service or every tool version.

Sources & further reading