can1357/oh-my-pi · error · RuntimeError

bridge call {name!r} failed

Error message

bridge call {name!r} failed

What it means

After parsing the bridge's JSON response, `_bridge_call` requires a dict with `ok: true`. If the body is a dict without `ok`, not a dict at all, or an error payload, it raises this RuntimeError — preferring the server-provided `error` message, with this generic fallback when the server didn't include one.

Source

Thrown at packages/coding-agent/src/eval/py/prelude.py:419

            headers={
                "Content-Type": "application/json",
                "Authorization": f"Bearer {token}",
            },
        )
        try:
            with _BRIDGE_OPENER.open(req) as resp:
                body = resp.read()
        except urllib.error.HTTPError as exc:
            body = exc.read()
        try:
            data = json.loads(body)
        except json.JSONDecodeError:
            raise RuntimeError(
                f"bridge call {name!r}: non-JSON response: {body[:200]!r}"
            ) from None
        if not isinstance(data, dict) or not data.get("ok"):
            msg = (data or {}).get("error") if isinstance(data, dict) else None
            raise RuntimeError(msg or f"bridge call {name!r} failed")
        return data.get("value")

    class _ToolCallable:
        """Invokes one host-side tool via the loopback HTTP bridge."""

        __slots__ = ("_name",)

        def __init__(self, name: str):
            self._name = name

        def __repr__(self) -> str:
            return f"<tool.{self._name}>"

        def __call__(self, args=None, /, **kwargs):
            if args is None:
                merged: dict = {}
            elif isinstance(args, dict):
                merged = dict(args)

View on GitHub (pinned to 9690622007)

Solutions

  1. Inspect the tool name and arguments — try a known-good call (e.g. a simple read) to distinguish 'this call failed' from 'bridge broken'.
  2. Verify the tool name exists in the current session's tool set (names may have changed between versions).
  3. Check the host/agent logs for the underlying tool failure that produced the empty error.
  4. Retry if the failure was transient (e.g. a command that timed out).

Example fix

// before
result = tool.bash({"command": "make test"})

// after
try:
    result = tool.bash({"command": "make test"})
except RuntimeError as e:
    if "failed" in str(e) and len(str(e)) < 40:
        print(f"tool.bash failed without details; check host logs")
    raise
Defensive patterns

Strategy: try-catch

Validate before calling

# no reliable pre-check; validate tool name against the session's tool list if exposed
# and verify bridge protocol version matches the prelude

Try / catch

try:
    result = tool.bash({"command": cmd})
except RuntimeError as e:
    msg = str(e)
    if msg.endswith("failed"):
        print(f"tool failed with no server message; check host logs")
    raise

Prevention

When it happens

Trigger: The host tool executed and failed without returning an `error` field; the bridge returned `ok: false` with no message; the response shape changed (e.g. an array or string instead of `{ok, value}`).

Common situations: Calling a tool whose host-side execution threw but failed to serialize an error message; calling an unknown/renamed tool name that the bridge rejects opaquely; version mismatch between the prelude and the host bridge protocol.

Related errors


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