can1357/oh-my-pi · error

rpc chunk payload exceeds the transport limit

Error message

rpc chunk payload exceeds the transport limit

What it means

After base64 decoding a chunk's payload, push verifies the decoded bytes do not exceed RPC_CHUNK_PAYLOAD_BYTES (256 KiB). This error is thrown when a single chunk carries more payload than one slice is allowed to hold, breaking the sender/receiver size contract even though the whole-frame ceiling might still be respected.

Source

Thrown at packages/coding-agent/src/modes/rpc/rpc-frame.ts:162

		}
		const { chunkId, index, count, byteLength } = value;
		if (
			typeof chunkId !== "string" ||
			chunkId.length === 0 ||
			chunkId.length > 128 ||
			!Number.isSafeInteger(index) ||
			!Number.isSafeInteger(count) ||
			!Number.isSafeInteger(byteLength) ||
			index < 0 ||
			count < 2 ||
			count > Math.ceil(MAX_RPC_REASSEMBLED_BYTES / RPC_CHUNK_PAYLOAD_BYTES) ||
			index >= count ||
			byteLength < MAX_RPC_FRAME_BYTES ||
			byteLength > MAX_RPC_REASSEMBLED_BYTES
		)
			throw new Error("invalid rpc chunk metadata");
		const bytes = decodeBase64(value.data);
		if (bytes.byteLength > RPC_CHUNK_PAYLOAD_BYTES) throw new Error("rpc chunk payload exceeds the transport limit");

		if (!this.#pending) {
			if (index !== 0) throw new Error("rpc chunk sequence must start at index 0");
			this.#pending = { chunkId, count, byteLength, nextIndex: 0, chunks: [], receivedBytes: 0 };
		}
		const pending = this.#pending;
		if (
			pending.chunkId !== chunkId ||
			pending.count !== count ||
			pending.byteLength !== byteLength ||
			pending.nextIndex !== index
		)
			throw new Error("rpc chunk sequence mismatch");
		pending.chunks.push(bytes);
		pending.receivedBytes += bytes.byteLength;
		pending.nextIndex++;
		if (pending.receivedBytes > pending.byteLength) throw new Error("rpc chunk sequence exceeds declared length");
		if (pending.nextIndex < pending.count) return undefined;

View on GitHub (pinned to 9690622007)

Solutions

  1. Slice the UTF-8 bytes in 256*1024-byte pieces: bytes.subarray(i*262144, (i+1)*262144).
  2. Match the receiver's RPC_CHUNK_PAYLOAD_BYTES constant exactly — do not invent a larger chunk size.
  3. Assert per-chunk decoded length ≤ 262144 on the sender before writing the line.

Example fix

// before: 1MiB slices
const slice = bytes.subarray(index * 1024 * 1024, (index + 1) * 1024 * 1024);
// after: 256KiB slices
const slice = bytes.subarray(index * 256 * 1024, (index + 1) * 256 * 1024);
Defensive patterns

Strategy: validation

Validate before calling

const CHUNK = 256 * 1024;
// pre-send check per chunk
if (chunkBuffer.byteLength > CHUNK) throw new Error(`chunk too large: ${chunkBuffer.byteLength} > ${CHUNK}`);

Try / catch

try {
  decoder.push(parsedLine);
} catch (err) {
  if (err instanceof Error && err.message === "rpc chunk payload exceeds the transport limit") {
    logger.error("sender chunk size exceeds 256KiB; align sender with receiver constants");
  } else throw err;
}

Prevention

When it happens

Trigger: A sender slicing the logical frame into pieces larger than 256 KiB (e.g. using a different chunk size constant); sending the entire frame as one chunk with count≥2 metadata; encoding overhead miscounted so decoded bytes exceed the slice size.

Common situations: Third-party implementations of protocol v2 that picked a bigger chunk size; constants changed independently on sender and receiver sides; confusion between base64 character count and decoded byte count.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/4b7ddc273613487a. Report an issue: GitHub.