can1357/oh-my-pi · error · RpcError

RPC protocol v2 negotiation failed

Error message

RPC protocol v2 negotiation failed

What it means

During RpcClient.start(), after capability checks confirm both sides support protocol v2, the client sends a 'negotiate_protocol' request with protocolVersion=2. If the server's response does not echo protocolVersion == 2, the client assumes negotiation failed, raises this RpcError, and stops the client process before re-raising. This guards against servers that advertise v2 support but refuse or mis-handle the negotiation handshake.

Source

Thrown at python/omp-rpc/src/omp_rpc/client.py:660

                    f"RPC process stopped before ready: {error}. Stderr: {stderr}"
                ) from error
            raise RpcTimeoutError(
                f"Timed out waiting for RPC ready signal. Stderr: {stderr}"
            )

        ready_event = self._ready_event
        if (
            ready_event is not None
            and ready_event.supported_protocol_versions is not None
            and 2 in ready_event.supported_protocol_versions
            and ready_event.max_frame_bytes == _MAX_RPC_FRAME_BYTES
            and ready_event.max_reassembled_frame_bytes == _MAX_RPC_REASSEMBLED_BYTES
        ):
            try:
                self._protocol_v2_enabled = True
                negotiation = self._request("negotiate_protocol", protocolVersion=2)
                if negotiation.get("protocolVersion") != 2:
                    raise RpcError("RPC protocol v2 negotiation failed")
                self._protocol_version = 2
            except BaseException:
                self.stop()
                raise

        if self._custom_tools:
            self.set_custom_tools(self._custom_tools)
        if self._host_uris:
            self.set_host_uris(self._host_uris)
        return self

    def stop(self) -> None:
        process = self._process
        if process is None:
            return

        self._stopping = True
        for pending_call in self._pending_host_tool_calls.values():

View on GitHub (pinned to 9690622007)

Solutions

  1. Upgrade or rebuild the omp server binary so its version matches the Python omp-rpc client package
  2. Pin the client and server to compatible versions (install both from the same release)
  3. Log the negotiate_protocol response payload to confirm what the server actually returned
  4. If a server genuinely cannot do v2, use a client/server pair whose capabilities do not advertise v2 so negotiation is skipped

Example fix

# before: mismatched versions
pip install -U omp-rpc   # client now expects v2, stale server binary remains

# after: keep both sides in sync
pip install -U omp-rpc omp  # or rebuild/replace the server binary to the matching release
Defensive patterns

Strategy: try-catch

Validate before calling

# check versions before start()
import omp_rpc
print("client:", omp_rpc.__version__)  # ensure matching server binary is installed

Type guard

def negotiation_ok(payload: dict) -> bool:
    return isinstance(payload, dict) and payload.get("protocolVersion") == 2

Try / catch

try:
    client.start()
except RpcError as e:
    if "protocol v2 negotiation failed" in str(e):
        upgrade_server_and_restart()  # then retry start()
    else:
        raise

Prevention

When it happens

Trigger: Calling start() on a client whose server reports v2-compatible capabilities (matching _MAX_RPC_REASSEMBLED_BYTES etc.) but whose 'negotiate_protocol' response payload lacks protocolVersion: 2 — e.g. an older or mismatched omp server binary, or a stub/test server returning an unexpected payload.

Common situations: Version skew between the Python client package and the installed omp server (client upgraded, server binary stale, or vice versa); custom/mock RPC servers that don't implement negotiate_protocol correctly; proxy wrappers that strip or rewrite response fields.

Related errors


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