{"record":{"id":"debf25cdcd54631b","repo":"can1357/oh-my-pi","slug":"rpc-frame-must-be-an-object","errorCode":null,"errorMessage":"rpc frame must be an object","messagePattern":"rpc frame must be an object","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/modes/rpc/rpc-frame.ts","lineNumber":142,"sourceCode":"\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\" ||\n\t\t\tchunkId.length === 0 ||\n\t\t\tchunkId.length > 128 ||\n\t\t\t!Number.isSafeInteger(index) ||\n\t\t\t!Number.isSafeInteger(count) ||\n\t\t\t!Number.isSafeInteger(byteLength) ||\n\t\t\tindex < 0 ||\n\t\t\tcount < 2 ||\n\t\t\tcount > Math.ceil(MAX_RPC_REASSEMBLED_BYTES / RPC_CHUNK_PAYLOAD_BYTES) ||\n\t\t\tindex >= count ||\n\t\t\tbyteLength < MAX_RPC_FRAME_BYTES ||\n\t\t\tbyteLength > MAX_RPC_REASSEMBLED_BYTES\n\t\t)\n\t\t\tthrow new Error(\"invalid rpc chunk metadata\");","sourceCodeStart":124,"sourceCodeEnd":160,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/modes/rpc/rpc-frame.ts#L124-L160","documentation":"RpcFrameDecoder.push expects every input line (after JSON.parse) to be a record (plain object). This error is thrown when a parsed JSONL line decodes to a non-object JSON value — a string, number, boolean, null, or an array — that is also not an rpc_chunk frame.","triggerScenarios":"Writing raw JSON values like `\"hello\"`, `42`, `null`, or `[1,2]` as RPC lines; a sender that JSON-stringifies a bare value instead of a frame object; a corrupt/truncated line that still parses as a scalar.","commonSituations":"Custom scripts piping debug output into the RPC stdin; a client SDK bug that drops the frame wrapper object; log lines accidentally written to the RPC channel.","solutions":["Always wrap payloads in a frame object with a `type` field before JSON.stringify.","Check that only frame objects are written to the RPC transport — route logs/diagnostics elsewhere.","Validate output on the sender side: JSON.parse(line) must yield an object before writing."],"exampleFix":"// before\nwrite(JSON.stringify(\"pong\"));\n// after\nwrite(JSON.stringify({ type: \"response\", id, success: true, result: \"pong\" }));","handlingStrategy":"type-guard","validationCode":"// pre-write validation on the sender side\nconst line = JSON.stringify(frame);\nif (typeof JSON.parse(line) !== \"object\" || JSON.parse(line) === null || Array.isArray(JSON.parse(line))) {\n  throw new Error(\"RPC frame must be a JSON object\");\n}","typeGuard":"function isRpcFrameObject(value: unknown): value is Record<string, unknown> {\n  return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}","tryCatchPattern":"try {\n  decoder.push(parsedLine);\n} catch (err) {\n  if (err instanceof Error && err.message === \"rpc frame must be an object\") {\n    logger.warn(\"ignoring non-object RPC line\", { line: truncated(parsedLine) });\n  } else throw err;\n}","preventionTips":["Wrap every payload in a typed frame object with a `type` field.","Keep logs and diagnostics off the RPC transport channel.","Validate parsed lines are objects before pushing to the decoder in adapters."],"tags":["rpc","validation","protocol","json"],"backgroundTag":"malformed-rpc-frame","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}