can1357/oh-my-pi · error
invalid rpc chunk data
Error message
invalid rpc chunk data
What it means
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.
Source
Thrown at packages/coding-agent/src/modes/rpc/rpc-frame.ts:129
};
const line = `${JSON.stringify(chunk)}\n`;
if (serializedFrameBytes(line.slice(0, -1)) > MAX_RPC_FRAME_BYTES)
throw new Error("RPC chunk exceeded the transport limit");
yield line;
}
}
function isRpcChunkFrame(value: unknown): value is RpcChunkFrame {
return isRecord(value) && value.type === "rpc_chunk";
}
function decodeBase64(data: unknown): Buffer {
if (
typeof data !== "string" ||
data.length === 0 ||
!/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/.test(data)
)
throw new Error("invalid rpc chunk data");
const bytes = Buffer.from(data, "base64");
if (bytes.toString("base64") !== data) throw new Error("invalid rpc chunk data");
return bytes;
}
/** Reassemble protocol v2 chunk frames after each JSONL line has been parsed. */
export class RpcFrameDecoder {
#pending?: PendingRpcChunks;
push(value: unknown): object | undefined {
if (!isRpcChunkFrame(value)) {
if (this.#pending) throw new Error("rpc chunk sequence interrupted");
if (!isRecord(value)) throw new Error("rpc frame must be an object");
return value;
}
const { chunkId, index, count, byteLength } = value;
if (
typeof chunkId !== "string" ||View on GitHub (pinned to 9690622007)
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.
Example fix
// before: URL-safe base64 from a web client
const data = btoa(String.fromCharCode(...bytes)).replace(/\+/g, '-').replace(/\//g, '_');
// after: standard base64
const data = Buffer.from(bytes).toString('base64'); Defensive patterns
Strategy: validation
Validate before calling
function isValidBase64Shape(data: unknown): data is string {
return typeof data === "string" &&
data.length > 0 &&
/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/.test(data);
}
// pre-send check
if (!isValidBase64Shape(chunk.data)) throw new Error("refusing to send non-canonical chunk data"); Type guard
function isCanonicalBase64(data: unknown): data is string {
if (typeof data !== "string" || data.length === 0) return false;
if (!/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/.test(data)) return false;
return Buffer.from(data, "base64").toString("base64") === data;
} Try / catch
try {
decoder.push(parsedLine);
} catch (err) {
if (err instanceof Error && err.message === "invalid rpc chunk data") {
logger.warn("dropping rpc_chunk with malformed base64 payload", { chunkId: parsedLine?.chunkId });
} else throw err;
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- rpc frame must be an object
- invalid rpc chunk metadata
- rpc chunk payload exceeds the transport limit
- rpc chunk sequence exceeds declared length
- RPC frame must be a JSON object
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/994feab0d4d7fc37.
Report an issue: GitHub.