Sandbox ID or Build ID
Not applicable: documentation/source-level control, no sandbox call
Environment
Timestamp of the issue
2026-07-16 17:31 CEST
Frequency
Happens every time
Expected behavior
The Codex streaming examples should carry an incomplete trailing fragment across onStdout callbacks and call JSON.parse / json.loads only for complete newline-terminated JSONL records. A final non-empty remainder should be flushed or rejected when the command completes.
Actual behavior
Both current examples split and parse each callback value independently. The JavaScript SDK forwards each decoded transport data event directly to onStdout; it does not buffer until a newline, and its own unit test deliberately splits a UTF-8 character across two data events. A valid Codex JSONL record split at the same supported event boundary is therefore parsed while incomplete.
Controlled result:
| Delivery |
Current JS example |
Remainder-buffered control |
| One complete line per callback |
2 records |
2 records |
| Same bytes in chunks of 19, 46, 74, and 3 characters |
SyntaxError: Unterminated string in JSON at position 19 |
2 records |
Claim boundary: this is a deterministic documentation-parser failure, not a claim that the E2B sandbox or Codex process itself fails.
Issue reproduction
- Use current
docs/agents/codex.mdx lines 201-247. The JavaScript handler is:
onStdout: (data) => {
for (const line of data.split('\n').filter(Boolean)) {
const event = JSON.parse(line)
console.log(`[${event.type}]`, event)
}
}
- Create two valid Codex-shaped JSONL records:
const records = [
{ type: 'thread.started', thread_id: 'emic-e2b-control' },
{ type: 'item.completed', item: { type: 'agent_message', text: 'refactor complete' } },
]
const jsonl = records.map(JSON.stringify).join('\n') + '\n'
- Call the documented handler with one complete JSONL line per callback. It parses 2 records.
- Call the same handler with the same bytes split at character positions 19, 65, and 139, representing supported transport/event boundaries. It throws on the first incomplete record.
- Run the same arbitrary chunks through a handler that preserves the trailing fragment between callbacks. It parses both records exactly once and in order.
Source confirmation: packages/js-sdk/src/sandbox/commands/commandHandle.ts dispatches each decoded data event directly to onStdout. packages/js-sdk/tests/sandbox/commands/commandHandle.test.ts, test decodes multibyte characters split across chunks, confirms event boundaries can split output bytes.
Additional context
Current source:
The Python example has the same structure with data.strip().split("\n") and json.loads(line), so it has the equivalent partial-record failure.
Suggested fix: keep a remainder buffer outside the callback, append each chunk, parse only complete newline-delimited records, and handle the final remainder after commands.run returns.
I searched this repository's issues and pull requests for the exact parser plus broader JSONL/streaming terms and found no matching report.
Sandbox ID or Build ID
Not applicable: documentation/source-level control, no sandbox call
Environment
Timestamp of the issue
2026-07-16 17:31 CEST
Frequency
Happens every time
Expected behavior
The Codex streaming examples should carry an incomplete trailing fragment across
onStdoutcallbacks and callJSON.parse/json.loadsonly for complete newline-terminated JSONL records. A final non-empty remainder should be flushed or rejected when the command completes.Actual behavior
Both current examples split and parse each callback value independently. The JavaScript SDK forwards each decoded transport data event directly to
onStdout; it does not buffer until a newline, and its own unit test deliberately splits a UTF-8 character across two data events. A valid Codex JSONL record split at the same supported event boundary is therefore parsed while incomplete.Controlled result:
SyntaxError: Unterminated string in JSON at position 19Claim boundary: this is a deterministic documentation-parser failure, not a claim that the E2B sandbox or Codex process itself fails.
Issue reproduction
docs/agents/codex.mdxlines 201-247. The JavaScript handler is:Source confirmation:
packages/js-sdk/src/sandbox/commands/commandHandle.tsdispatches each decoded data event directly toonStdout.packages/js-sdk/tests/sandbox/commands/commandHandle.test.ts, testdecodes multibyte characters split across chunks, confirms event boundaries can split output bytes.Additional context
Current source:
b3047d53c4a1cef90e9b5e1193b1c6ed7366e7bce68b876689d20cee68c1d589802ec45c91d9f873The Python example has the same structure with
data.strip().split("\n")andjson.loads(line), so it has the equivalent partial-record failure.Suggested fix: keep a remainder buffer outside the callback, append each chunk, parse only complete newline-delimited records, and handle the final remainder after
commands.runreturns.I searched this repository's issues and pull requests for the exact parser plus broader JSONL/streaming terms and found no matching report.