can1357/oh-my-pi · error · RpcCommandError

RPC command failed

Error message

RPC command failed

What it means

#getData() unwraps a successful RpcResponse; when the response carries success:false it throws RpcCommandError carrying the server's error message, the command name, and an optional machine-readable code. This is the transport for every server-side command failure (invalid command, session errors, internal server exceptions).

Source

Thrown at packages/coding-agent/src/modes/rpc/rpc-client.ts:1245

	): void {
		if (!this.#process?.stdin) {
			throw new Error("Client not started");
		}
		const stdin = this.#process.stdin;
		stdin.write(`${JSON.stringify(frame)}\n`);
		if (!("flush" in stdin)) return;
		const flushResult = (stdin as FileSink).flush();
		if (isPromise(flushResult)) {
			flushResult.catch((err: Error) => {
				onError?.(err);
			});
		}
	}

	#getData<T>(response: RpcResponse): T {
		if (!response.success) {
			const errorResponse = response as Extract<RpcResponse, { success: false }>;
			throw new RpcCommandError(errorResponse.error, errorResponse.command, errorResponse.code);
		}
		// Type assertion: we trust response.data matches T based on the command sent.
		// This is safe because each public method specifies the correct T for its command.
		const successResponse = response as Extract<RpcResponse, { success: true; data: unknown }>;
		return successResponse.data as T;
	}
}

View on GitHub (pinned to 9690622007)

Solutions

  1. Read error.command and error.code on the RpcCommandError to pinpoint which command failed and why.
  2. Catch RpcCommandError specifically rather than generic Error.
  3. Align client and server versions so the command exists.
  4. Fix the parameters passed to the failing command per the server's error message.

Example fix

// before
const msgs = await client.getMessages(); // throws generic Error
// after
try {
  const msgs = await client.getMessages();
} catch (err) {
  if (err instanceof RpcCommandError && err.command === "get_messages") {
    // handle per err.code
  } else throw err;
}
Defensive patterns

Strategy: try-catch

Validate before calling

if (!supportedCommands.has(command.type)) throw new Error(`unsupported command: ${command.type}`);

Type guard

function isRpcCommandError(e: unknown): e is RpcCommandError {
  return e instanceof RpcCommandError;
}

Try / catch

try {
  const data = await client.getMessages();
} catch (e) {
  if (isRpcCommandError(e)) {
    switch (e.code) {
      case "SESSION_NOT_FOUND": return fallbackToEmptyHistory();
      default: throw e;
    }
  }
  throw e;
}

Prevention

When it happens

Trigger: Any command sent via #send whose RpcResponse comes back success:false — e.g. get_messages on an unknown session, an unsupported command, or the server throwing while handling a request.

Common situations: Calling a command the child binary doesn't support (version skew); referencing a session/prompt that doesn't exist; server-side validation or internal errors; sending commands to a busy or closing server.

Related errors


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