{"record":{"id":"5577bd9207936f8b","repo":"stablyai/orca","slug":"ndjson-line-exceeds-max-maxlinebytes-bytes-l","errorCode":null,"errorMessage":"NDJSON line exceeds max ${maxLineBytes} bytes (${lineBytes} bytes encoded)","messagePattern":"NDJSON line exceeds max (.+?) bytes \\((.+?) bytes encoded\\)","errorType":"exception","errorClass":"NdjsonLineTooLongError","httpStatus":null,"severity":"error","filePath":"src/main/daemon/ndjson.ts","lineNumber":17,"sourceCode":"export const NDJSON_MAX_LINE_BYTES = 16 * 1024 * 1024\n\nexport class NdjsonLineTooLongError extends Error {\n  constructor(\n    readonly lineBytes: number,\n    readonly maxLineBytes: number\n  ) {\n    super(`NDJSON line exceeds max ${maxLineBytes} bytes (${lineBytes} bytes encoded)`)\n    this.name = 'NdjsonLineTooLongError'\n  }\n}\n\nexport function encodeNdjson(msg: unknown, maxLineBytes = NDJSON_MAX_LINE_BYTES): string {\n  const line = JSON.stringify(msg)\n  const lineBytes = Buffer.byteLength(line, 'utf8')\n  if (lineBytes > maxLineBytes) {\n    throw new NdjsonLineTooLongError(lineBytes, maxLineBytes)\n  }\n  return `${line}\\n`\n}\n\nexport type NdjsonParser = {\n  feed(chunk: string): void\n  reset(): void\n}\n\nexport type NdjsonParserOptions = {\n  maxLineBytes?: number\n}\n\nexport function createNdjsonParser(\n  onMessage: (msg: unknown) => void,\n  onError?: (err: Error) => void,\n  options: NdjsonParserOptions = {}\n): NdjsonParser {","sourceCodeStart":1,"sourceCodeEnd":35,"githubUrl":"https://github.com/stablyai/orca/blob/1136503c6a231a16dce8f921f6fadb63d181e8db/src/main/daemon/ndjson.ts#L1-L35","documentation":"NdjsonLineTooLongError: encodeNdjson throws when the JSON-serialized message exceeds the byte limit (default 16 MB, NDJSON_MAX_LINE_BYTES). This is a hard backstop so a daemon socket peer that never sends a newline — or a single oversized frame — cannot grow the parser buffer without bound. The error carries the actual and maximum byte counts.","triggerScenarios":"encodeNdjson(msg) where Buffer.byteLength(JSON.stringify(msg), 'utf8') exceeds maxLineBytes. The parser path (createNdjsonParser) reports the same message via onError when an incoming line exceeds the limit.","commonSituations":"Embedding a very large base64 blob, screenshot, or scrollback payload in a single NDJSON frame; a payload that grew past the limit after a format change; a peer streaming an unbounded paste without chunking.","solutions":["Chunk the large payload into multiple smaller NDJSON messages (e.g., the history seed transfer protocol) instead of one frame.","Raise maxLineBytes deliberately only if you control both peers and understand the memory cost.","Strip/avoid embedding large binary blobs inline; reference them by transfer id instead.","On the parser side, handle the onError callback to surface the oversized-line condition rather than silently dropping data."],"exampleFix":"// before: one giant frame\nencodeNdjson({ scrollback: hugeBase64 })\n\n// after: chunked transfer\nconst metrics = measureTerminalHistorySeed([hugeBase64])\nconst id = registry.start(clientId, metrics)\nfor (const chunk of iterateTerminalHistorySeedChunks([hugeBase64])) {\n  registry.append(clientId, id, i++, chunk)\n}","handlingStrategy":"validation","validationCode":"import { NDJSON_MAX_LINE_BYTES } from './ndjson'\nfunction fitsNdjson(msg: unknown, max = NDJSON_MAX_LINE_BYTES): boolean {\n  return Buffer.byteLength(JSON.stringify(msg), 'utf8') <= max\n}\nif (!fitsNdjson(msg)) { /* chunk the payload instead */ }","typeGuard":"import { NdjsonLineTooLongError } from './ndjson'\nfunction isNdjsonTooLong(e: unknown): boolean {\n  return e instanceof NdjsonLineTooLongError\n}","tryCatchPattern":"try {\n  sock.write(encodeNdjson(msg))\n} catch (e) {\n  if (e instanceof NdjsonLineTooLongError) {\n    // split into chunked transfer messages\n    sendChunked(sock, msg)\n  } else { throw e }\n}","preventionTips":["Size-check payloads with Buffer.byteLength before encoding.","Use the seed-transfer protocol for large scrollback instead of one inline frame.","Handle the parser's onError so oversized incoming lines are surfaced, not silently dropped."],"tags":["ndjson","serialization","limits","protocol"],"backgroundTag":null,"analyzedSha":"1136503c6a231a16dce8f921f6fadb63d181e8db","analyzedAt":"2026-08-12T23:15:58.167Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}