Skip to content

fix(client): discard truncated JSON document on mid-stream EOF#97

Open
krynju wants to merge 1 commit into
mainfrom
kr/streaming-truncated-chunk
Open

fix(client): discard truncated JSON document on mid-stream EOF#97
krynju wants to merge 1 commit into
mainfrom
kr/streaming-truncated-chunk

Conversation

@krynju

@krynju krynju commented Jun 26, 2026

Copy link
Copy Markdown
Member

Problem

JSONChunkReader._read_json_chunk brace-counts one JSON document off the response BufferStream, but its while !eof(io) loop also terminates on end-of-stream. When a streaming response closes mid-document (a dropped/cancelled connection, or a server that ends the stream partway through an object), the partial bytes are handed to JSON.parse, which throws Unexpected end of input. In the streaming client this surfaces as a logged error:

┌ Error: exception reading chunk
│   exception = Unexpected end of input
│   Around: ...tatuses":...
│      [14] iterate(::JSONChunkReader, ...) @ chunk_readers.jl:104
│      ...juliaweb_http.jl:330 / :333

Fix

Track completeness in the object/array and string branches of _read_json_chunk: a document is only complete when it balances (depth == 0) or the string's terminating quote is read. If the loop exits via EOF while still incomplete, return UInt8[] so iterate's existing isempty(chunk_bytes) && return nothing treats it as a clean end of stream rather than parsing a truncated document. Complete documents (always ≥2 bytes) are unaffected, including }/] inside string values and nested structures.

Tests

  • Updated jsonchunk4 — it previously asserted the buggy @test_throws TaskFailedException on a truncated trailing object; it now asserts the document is discarded, iteration ends without throwing, and the complete documents read before it are still yielded.
  • Added _read_json_chunk unit tests: truncated object ({"statuses":), truncated nested object, truncated array ([1, 2), truncated string ("dev/termina), and complete-then-truncated.

Full chunk-reader suite (62 tests) passes.

Bumps version to 0.2.4.

🤖 Generated with Claude Code

JSONChunkReader's `_read_json_chunk` brace-counts one JSON document off the
response BufferStream, but its `while !eof(io)` loop also terminates on
end-of-stream. When a streaming response closed mid-document (a dropped or
cancelled connection), the partial bytes were handed to the JSON parser and
threw `Unexpected end of input`, surfacing as a logged "exception reading chunk"
error in the streaming consumer.

Track completeness in the object/array and string branches: only the balanced
close (`depth == 0`, or the terminating quote) marks the document complete. If
the loop exits via EOF while incomplete, return empty so `iterate` treats it as
a clean end of stream instead of parsing a truncated document. Complete
documents are unaffected.

Updates the existing jsonchunk4 test (it asserted the old throw-on-truncation
behavior) and adds `_read_json_chunk` unit tests for truncated object / nested
object / array / string, and complete-then-truncated. Bumps to 0.2.4.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@krynju krynju marked this pull request as ready for review June 26, 2026 14:29
@krynju krynju requested a review from tanmaykm June 26, 2026 14:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant