{"record":{"id":"994feab0d4d7fc37","repo":"can1357/oh-my-pi","slug":"invalid-rpc-chunk-data","errorCode":null,"errorMessage":"invalid rpc chunk data","messagePattern":"invalid rpc chunk data","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/modes/rpc/rpc-frame.ts","lineNumber":129,"sourceCode":"\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;\n}\n\n/** Reassemble protocol v2 chunk frames after each JSONL line has been parsed. */\nexport class RpcFrameDecoder {\n\t#pending?: PendingRpcChunks;\n\n\tpush(value: unknown): object | undefined {\n\t\tif (!isRpcChunkFrame(value)) {\n\t\t\tif (this.#pending) throw new Error(\"rpc chunk sequence interrupted\");\n\t\t\tif (!isRecord(value)) throw new Error(\"rpc frame must be an object\");\n\t\t\treturn value;\n\t\t}\n\t\tconst { chunkId, index, count, byteLength } = value;\n\t\tif (\n\t\t\ttypeof chunkId !== \"string\" ||","sourceCodeStart":111,"sourceCodeEnd":147,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/modes/rpc/rpc-frame.ts#L111-L147","documentation":"decodeBase64 validates the `data` field of an rpc_chunk frame before decoding: it must be a non-empty string containing only valid base64 characters in valid padding shape. This error is thrown when the regex check fails, i.e. the chunk payload is missing, empty, or not syntactically valid base64.","triggerScenarios":"Pushing a parsed rpc_chunk object to RpcFrameDecoder.push where `data` is undefined/null/empty string, contains whitespace/newlines (e.g. line-splitting mangled it), uses URL-safe base64 (-/_) instead of standard, or has wrong padding.","commonSituations":"A hand-rolled client URL-safe-encodes payloads; a proxy re-wraps JSONL lines and inserts CRLF inside the data field; a test fixture passes a placeholder string; the sender wrote an empty final chunk.","solutions":["Encode chunk payloads with Buffer.from(bytes).toString('base64') (standard alphabet, correct padding) on the sender side.","Verify the JSONL transport preserves the line intact — no newline/whitespace injection inside the data field.","Check that `data` is actually populated on the chunk frame before sending."],"exampleFix":"// before: URL-safe base64 from a web client\nconst data = btoa(String.fromCharCode(...bytes)).replace(/\\+/g, '-').replace(/\\//g, '_');\n// after: standard base64\nconst data = Buffer.from(bytes).toString('base64');","handlingStrategy":"validation","validationCode":"function isValidBase64Shape(data: unknown): data is string {\n  return typeof data === \"string\" &&\n    data.length > 0 &&\n    /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/.test(data);\n}\n// pre-send check\nif (!isValidBase64Shape(chunk.data)) throw new Error(\"refusing to send non-canonical chunk data\");","typeGuard":"function isCanonicalBase64(data: unknown): data is string {\n  if (typeof data !== \"string\" || data.length === 0) return false;\n  if (!/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/.test(data)) return false;\n  return Buffer.from(data, \"base64\").toString(\"base64\") === data;\n}","tryCatchPattern":"try {\n  decoder.push(parsedLine);\n} catch (err) {\n  if (err instanceof Error && err.message === \"invalid rpc chunk data\") {\n    logger.warn(\"dropping rpc_chunk with malformed base64 payload\", { chunkId: parsedLine?.chunkId });\n  } else throw err;\n}","preventionTips":["Always produce base64 via Buffer.from(bytes).toString('base64').","Never use base64url (-/_) alphabets for rpc_chunk data.","Ensure the JSONL transport writes each chunk as one intact line with no injected whitespace."],"tags":["rpc","base64","validation","protocol"],"backgroundTag":"invalid-base64-payload","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}