jq -s collects all JSON input values into one array for that invocation. Appending each invocation to the same destination creates a stream of arrays, not an updated single array. Decide whether the destination is a snapshot or an event log.
Reproduce the boundary in a disposable fixture
Convert a stream of JSON objects into one valid array and keep repeated updates valid.
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.
printf '%s
' '{"id":1}' '{"id":2}' > events.json
jq -s '.' events.json > snapshot.json
jq -e 'length == 2 and .[0].id == 1' snapshot.json
# A second complete snapshot should replace the first.
jq -s '.' events.json > snapshot.next.json
mv snapshot.next.json snapshot.json
jq -s 'length' snapshot.json
# Shows 1 top-level JSON value, not two appended arrays.
printf '%s\n' '{"id":3}' > delta.json
jq -s '.[0] + .[1:]' snapshot.json delta.json > combined.next.json
jq -e 'length == 3 and .[2].id == 3' combined.next.json
Observed result
true
1
trueWhat the result means
The source contains two complete JSON values separated by whitespace. Slurp produces a single top-level array containing both objects. The last command slurps the output again solely to count top-level values: its result is 1. This is different from the array length of 2. A file can be acceptable to jq as a stream while still failing a consumer that expects one JSON document.
Choose the correction for your workflow
For a snapshot, write a new output file and replace the destination only after jq succeeds. Use a temporary path in the same filesystem and a shell conditional in production so a parse failure does not replace the last good output. Never redirect output onto the input path: the shell can truncate it before jq reads it. Coordinate with a producer that may be writing concurrently; a half-written source is not a stable snapshot. For an append-only log, JSON Lines may be a better contract, but its reader must explicitly support multiple records. If each source file contains only new events to append, the final fixture expression combines one existing array with all subsequent object inputs. Validate that the old file contains exactly one array, write to a separate candidate, inspect the result and replace only after success. Retrying the same delta appends it again; exactly-once processing or deduplication needs a stable event key and a separate policy. A full recurring source snapshot must not be treated as a new-event delta.
Limits and the next check
This fixture illustrates replacement in a private directory; it is not a concurrent writer or crash-durability test. Slurp loads all input values into memory. For a large or unbounded stream, choose an incremental record-oriented consumer instead. Re-running slurp cannot invent identity, deduplicate repeated source events or merge partial updates; those require an explicit application rule.
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.