can1357/oh-my-pi · error
Unsupported RPC protocol version: ${version}
Error message
Unsupported RPC protocol version: ${version} What it means
RpcFrameEncoder.setProtocolVersion() only accepts protocol versions 1 or 2. Passing any other version number throws immediately, since the encoder cannot emit frames for an unknown wire protocol.
Source
Thrown at packages/coding-agent/src/modes/rpc/rpc-frame.ts:277
if (serializedFrameBytes(json) <= MAX_RPC_FRAME_BYTES) return `${json}\n`;
}
return `${JSON.stringify(overflowFrame(compacted))}\n`;
}
/** Serialize a complete JSONL frame while enforcing the transport byte ceiling. */
export function encodeRpcFrame(frame: object, streamedMessageCount = 0, streamedMessages?: readonly unknown[]): string {
return encodeRpcFrameFromJson(frame, JSON.stringify(frame), streamedMessageCount, streamedMessages);
}
/** Stateful encoder that tracks which messages a client has already received. */
export class RpcFrameEncoder {
#streamedMessages: unknown[] = [];
#protocolVersion: RpcProtocolVersion = 1;
#chunkCounter = 0;
setProtocolVersion(version: number): void {
if (version !== 1 && version !== 2) throw new Error(`Unsupported RPC protocol version: ${version}`);
this.#protocolVersion = version;
}
/**
* Encode one logical frame into physical JSONL lines. Encoder bookkeeping runs
* eagerly; only chunk emission is lazy, so a chunked result can be streamed to
* stdout with backpressure without holding the whole transport in memory. The
* returned iterable MUST be fully consumed exactly once.
*/
encodeFrames(frame: object): Iterable<string> {
if (isRecord(frame) && frame.type === "agent_start") this.#streamedMessages = [];
const json = JSON.stringify(frame);
let frames: Iterable<string>;
let singleFrame: string | undefined;
if (this.#protocolVersion === 2 && serializedFrameBytes(json) > MAX_RPC_FRAME_BYTES) {
const compacted = compactTerminalFrame(frame, this.#streamedMessages.length, this.#streamedMessages);
// Reuse the original serialization when compaction was a no-op.
const compactedJson = compacted === frame ? json : JSON.stringify(compacted);View on GitHub (pinned to 9690622007)
Solutions
- Only call setProtocolVersion with 1 or 2; clamp or map other values before the call.
- Ensure the handshake passes a number, not a string: setProtocolVersion(Number(handshake.version)).
- Upgrade both processes to matching versions of the RPC implementation so the advertised version is supported.
- Default to version 1 when the negotiated version is unknown rather than forwarding it blindly.
Example fix
// before encoder.setProtocolVersion(handshake.protocolVersion); // e.g. 3 from newer peer // after const v = handshake.protocolVersion; encoder.setProtocolVersion(v === 2 ? 2 : 1);
Defensive patterns
Strategy: validation
Validate before calling
const SUPPORTED_VERSIONS = [1, 2] as const;
function assertSupportedVersion(v: number): asserts v is 1 | 2 {
if (v !== 1 && v !== 2) throw new Error(`client cannot speak protocol ${v}`);
}
assertSupportedVersion(handshake.protocolVersion); Type guard
function isSupportedProtocolVersion(v: unknown): v is 1 | 2 {
return v === 1 || v === 2;
} Try / catch
try {
encoder.setProtocolVersion(negotiated);
} catch (err) {
if (String(err.message).startsWith("Unsupported RPC protocol version")) {
encoder.setProtocolVersion(1); // graceful fallback
} else throw err;
} Prevention
- Negotiate protocol version numerically, not as a string
- Keep both peers on the same build/version of the RPC layer
- Clamp or fall back instead of forwarding unknown versions
- Log the negotiated version at connection setup for debugging
When it happens
Trigger: Calling encoder.setProtocolVersion(3) (or 0, -1, 2.5, NaN) during RPC client/server handshake when the peers advertise an unsupported protocolVersion.
Common situations: Client and server are different builds with mismatched protocol versions; a new protocol version was introduced in the server but the embedded/older encoder doesn't know it; handshake code forwards a raw string ('2') instead of a number.
Related errors
- invalid glob `{pattern}`: {error}
- Replacement text is not valid UTF-8: {err}
- RPC chunk received before protocol negotiation
- RPC protocol v2 negotiation failed
- RPC chunk exceeded the transport limit
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/23a8af01b8bae590.
Report an issue: GitHub.