can1357/oh-my-pi · error · RpcProcessExitError

str(self._closed_error)

Error message

str(self._closed_error)

What it means

RpcProcessExitError is raised from the agent_end wait loop when the client has detected the RPC server process closed. The message is str(self._closed_error), the underlying reason the process/reader terminated (non-zero exit, EOF, crash).

Source

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

        if streamed_prefix_count > len(streamed_messages):
            raise RpcError(
                "Compacted agent_end references "
                f"{streamed_prefix_count} streamed messages, but only "
                f"{len(streamed_messages)} were retained"
            )
        return streamed_messages[:streamed_prefix_count] + terminal.messages

    def _wait_for_agent_end(
        self,
        start_index: int,
        start_async_error_index: int,
        timeout: float | None = None,
    ) -> tuple[RpcAgentEvent, ...]:
        deadline = time.monotonic() + (timeout if timeout is not None else 60.0)
        with self._event_condition:
            while True:
                if self._closed_error is not None:
                    raise RpcProcessExitError(str(self._closed_error))

                if start_index < self._events.offset:
                    raise RpcError(
                        "Event history limit was exceeded while waiting for agent_end. "
                        "Increase max_event_history to retain more streamed events."
                    )

                if start_async_error_index < self._async_errors.offset:
                    raise RpcError(
                        "Async error history limit was exceeded while waiting for agent_end. "
                        "Increase max_event_history if your host needs to retain more background failures."
                    )

                async_errors = self._async_errors.snapshot_from(start_async_error_index)
                if len(async_errors) > 0:
                    raise async_errors[0]

                event_payloads = self._events.snapshot_from(start_index)

View on GitHub (pinned to 9690622007)

Solutions

  1. Inspect the embedded closed_error/stderr to find why the server process exited
  2. Check server stderr (client.stderr) for a traceback or OOM/kill message
  3. Wrap waits in try/except RpcProcessExitError and restart the client before retrying
  4. Verify the server binary/version is compatible and not being killed by your test harness (e.g. process-group kills)

Example fix

try:
    events = client.wait_for_agent_end(timeout=120)
except RpcProcessExitError as exc:
    print("server died:", exc, "stderr:", client.stderr)
    client = make_client(...)  # restart before retrying
Defensive patterns

Strategy: try-catch

Validate before calling

if client.poll() is not None:  # process already exited
    client = restart_client()

Try / catch

try:
    events = client.wait_for_agent_end(timeout=120)
except RpcProcessExitError as exc:
    log.error("server exited: %s; stderr=%s", exc, client.stderr)
    client = make_client(...)  # recreate before retrying

Prevention

When it happens

Trigger: Calling wait_for_agent_end (or an API that waits for events) after the omp server subprocess died: crash, kill, OOM, bad binary path, or a server-side unhandled exception closing stdout.

Common situations: Server binary killed by a signal (e.g. stop/timeout tests killing the process group), server crashing mid-run, attempting to wait on a client whose process already exited, environment missing the omp executable.

Related errors


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