Summary
Opening the Usage page can terminate the entire t3@latest Node process when a Codex session rollout contains one very large JSONL record.
In the observed case:
- 7 days worked.
- 30 days and 90 days showed zero usage and then crashed the server.
- The longer windows included an older Codex rollout with one 516.47 MiB line.
- That line was a non-usage
event_msg -> patch_apply_end -> delete record.
- Removing only that irrelevant record made both 30-day and 90-day scans complete successfully.
Environment
- Windows
- Node.js v24.15.0
t3@latest, launched with the local web server
- Codex transcripts under the normal
.codex/sessions directory
Crash
node:internal/readline/interface:652
this[kLine_buffer] += string;
^
RangeError: Invalid string length
at [_normalWrite] [as _normalWrite] (node:internal/readline/interface:652:31)
at ReadStream.ondata (node:internal/readline/interface:263:23)
at ReadStream.emit (node:events:509:28)
at addChunk (node:internal/streams/readable:563:12)
at readableAddChunkPushByteMode (node:internal/streams/readable:514:3)
at Readable.push (node:internal/streams/readable:394:5)
at node:internal/fs/streams:293:14
at FSReqCallback.wrapper [as oncomplete] (node:fs:670:5)
Root cause
apps/server/src/usage/usageTranscriptReader.ts reads each transcript with:
NodeReadline.createInterface({
input: NodeFS.createReadStream(filePath, { encoding: "utf8" }),
crlfDelay: Infinity,
});
Node's readline accumulates an entire line into a JavaScript string before T3 can apply mightCarryUsage. A sufficiently large record exceeds V8's maximum string length and throws from the stream's data callback. The surrounding try/catch does not prevent the process-level crash.
Measured transcript:
- Total file size before workaround: 551,526,950 bytes
- JSONL records: 3,403
- Oversized record: line 3,387
- Oversized record length: 541,561,318 bytes
- Record kind:
event_msg -> patch_apply_end -> delete
- File remained correctly newline-delimited
Workaround validation
After preserving the original transcript and removing only that non-usage line:
- Active transcript size: 9,965,632 bytes
- Remaining records: 3,402
- Largest remaining line: 106,482 bytes
- 30-day scan: 753 files, 1,559,096,780 bytes, 32,808 usage records, 0 failed files
- 90-day scan: 753 files, 1,559,126,792 bytes, 32,811 usage records, 0 failed files
Both scans used T3 Code's current listTranscriptFiles and readTranscriptRecords implementation directly.
Expected behavior
An oversized or malformed transcript record should not terminate the T3 server. The Usage response should either:
- skip an oversized record that cannot affect usage, or
- skip/report the affected transcript while returning partial usage.
Suggested direction
Use a bounded byte/chunk line reader instead of unbounded Node readline. It should stop buffering a record after a conservative limit, drain through its newline without decoding the whole record, and continue scanning later records.
A focused test could expose an injectable low line limit so the regression can be covered without committing a hundreds-of-megabytes fixture.
Possibly related but not equivalent: #996 reports crashes around a heavy thread, without this Usage-page stack or transcript-reader path.
Summary
Opening the Usage page can terminate the entire
t3@latestNode process when a Codex session rollout contains one very large JSONL record.In the observed case:
event_msg -> patch_apply_end -> deleterecord.Environment
t3@latest, launched with the local web server.codex/sessionsdirectoryCrash
Root cause
apps/server/src/usage/usageTranscriptReader.tsreads each transcript with:Node's
readlineaccumulates an entire line into a JavaScript string before T3 can applymightCarryUsage. A sufficiently large record exceeds V8's maximum string length and throws from the stream's data callback. The surroundingtry/catchdoes not prevent the process-level crash.Measured transcript:
event_msg -> patch_apply_end -> deleteWorkaround validation
After preserving the original transcript and removing only that non-usage line:
Both scans used T3 Code's current
listTranscriptFilesandreadTranscriptRecordsimplementation directly.Expected behavior
An oversized or malformed transcript record should not terminate the T3 server. The Usage response should either:
Suggested direction
Use a bounded byte/chunk line reader instead of unbounded Node
readline. It should stop buffering a record after a conservative limit, drain through its newline without decoding the whole record, and continue scanning later records.A focused test could expose an injectable low line limit so the regression can be covered without committing a hundreds-of-megabytes fixture.
Possibly related but not equivalent: #996 reports crashes around a heavy thread, without this Usage-page stack or transcript-reader path.