{"record":{"id":"2828425a73fe67ad","repo":"can1357/oh-my-pi","slug":"rpc-chunk-exceeded-the-transport-limit","errorCode":null,"errorMessage":"RPC chunk exceeded the transport limit","messagePattern":"RPC chunk exceeded the transport limit","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/modes/rpc/rpc-frame.ts","lineNumber":114,"sourceCode":"\t\tyield `${JSON.stringify(overflowFrame(frame))}\\n`;\n\t\treturn;\n\t}\n\tconst bytes = Buffer.from(json, \"utf8\");\n\tconst count = Math.ceil(byteLength / RPC_CHUNK_PAYLOAD_BYTES);\n\tfor (let index = 0; index < count; index++) {\n\t\tconst chunk: RpcChunkFrame = {\n\t\t\ttype: \"rpc_chunk\",\n\t\t\tchunkId,\n\t\t\tindex,\n\t\t\tcount,\n\t\t\tbyteLength,\n\t\t\tdata: bytes\n\t\t\t\t.subarray(index * RPC_CHUNK_PAYLOAD_BYTES, (index + 1) * RPC_CHUNK_PAYLOAD_BYTES)\n\t\t\t\t.toString(\"base64\"),\n\t\t};\n\t\tconst line = `${JSON.stringify(chunk)}\\n`;\n\t\tif (serializedFrameBytes(line.slice(0, -1)) > MAX_RPC_FRAME_BYTES)\n\t\t\tthrow new Error(\"RPC chunk exceeded the transport limit\");\n\t\tyield line;\n\t}\n}\n\nfunction isRpcChunkFrame(value: unknown): value is RpcChunkFrame {\n\treturn isRecord(value) && value.type === \"rpc_chunk\";\n}\n\nfunction decodeBase64(data: unknown): Buffer {\n\tif (\n\t\ttypeof data !== \"string\" ||\n\t\tdata.length === 0 ||\n\t\t!/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/.test(data)\n\t)\n\t\tthrow new Error(\"invalid rpc chunk data\");\n\tconst bytes = Buffer.from(data, \"base64\");\n\tif (bytes.toString(\"base64\") !== data) throw new Error(\"invalid rpc chunk data\");\n\treturn bytes;","sourceCodeStart":96,"sourceCodeEnd":132,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/modes/rpc/rpc-frame.ts#L96-L132","documentation":"encodeChunkedRpcFrames splits an oversized logical frame into protocol-v2 chunk lines, each of which must individually fit within MAX_RPC_FRAME_BYTES (1 MiB). This error is thrown when a single serialized chunk line exceeds that transport ceiling, which should be impossible from the encoder's own 256 KiB payload slices and indicates corrupted internal constants or tampered serialization. It is an internal-invariant guard, not a user-input validation.","triggerScenarios":"Calling RpcFrameEncoder.encodeFrames (via encode) under protocol v2 with a frame larger than MAX_RPC_FRAME_BYTES, where a generated 256 KiB base64 chunk line plus JSON metadata exceeds MAX_RPC_FRAME_BYTES — only possible if RPC_CHUNK_PAYLOAD_BYTES/MAX_RPC_FRAME_BYTES constants are inconsistent or JSON escaping of chunkId blows up the line.","commonSituations":"Almost never hit in practice; a fork or patch that changed chunk payload size without re-checking the frame limit, or a downstream build that overrode the constants.","solutions":["Keep RPC_CHUNK_PAYLOAD_BYTES comfortably below MAX_RPC_FRAME_BYTES (256 KiB payload → ~350 KiB base64 line) and do not override either constant.","Ensure chunkId stays short (≤128 chars) so JSON.stringify(chunk) metadata cannot inflate the line.","If you control the sender, reduce the logical frame via compactTerminalFrame/shrink paths before chunking."],"exampleFix":"// before: custom constants in a fork\nconst RPC_CHUNK_PAYLOAD_BYTES = 900 * 1024; // near the 1MiB line limit\n// after\nconst RPC_CHUNK_PAYLOAD_BYTES = 256 * 1024; // safely under MAX_RPC_FRAME_BYTES","handlingStrategy":"try-catch","validationCode":"import { MAX_RPC_FRAME_BYTES } from \"./rpc-frame\";\n// chunk lines from a 256KiB payload slice cannot exceed this unless constants drifted\nif (Buffer.byteLength(JSON.stringify(chunk), \"utf8\") + 1 > MAX_RPC_FRAME_BYTES) {\n  throw new Error(\"chunk size configuration inconsistent with transport limit\");\n}","typeGuard":null,"tryCatchPattern":"try {\n  for (const line of encoder.encodeFrames(frame)) process.stdout.write(line);\n} catch (err) {\n  if (err instanceof Error && err.message === \"RPC chunk exceeded the transport limit\") {\n    logger.error(\"RPC chunking constants are inconsistent; frame dropped\", { frameType: frame.type });\n  } else throw err;\n}","preventionTips":["Never fork or override MAX_RPC_FRAME_BYTES / RPC_CHUNK_PAYLOAD_BYTES independently.","Keep chunkId short (≤128 chars).","Rely on compactTerminalFrame/shrink paths to reduce frames before chunking."],"tags":["rpc","protocol","frame-size","internal-invariant"],"backgroundTag":"rpc-frame-size-limit-exceeded","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}