{"record":{"id":"d56d2a39d6889cbe","repo":"can1357/oh-my-pi","slug":"bridge-call-name-r-failed","errorCode":null,"errorMessage":"bridge call {name!r} failed","messagePattern":"bridge call (.+?) failed","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/eval/py/prelude.py","lineNumber":419,"sourceCode":"            headers={\n                \"Content-Type\": \"application/json\",\n                \"Authorization\": f\"Bearer {token}\",\n            },\n        )\n        try:\n            with _BRIDGE_OPENER.open(req) as resp:\n                body = resp.read()\n        except urllib.error.HTTPError as exc:\n            body = exc.read()\n        try:\n            data = json.loads(body)\n        except json.JSONDecodeError:\n            raise RuntimeError(\n                f\"bridge call {name!r}: non-JSON response: {body[:200]!r}\"\n            ) from None\n        if not isinstance(data, dict) or not data.get(\"ok\"):\n            msg = (data or {}).get(\"error\") if isinstance(data, dict) else None\n            raise RuntimeError(msg or f\"bridge call {name!r} failed\")\n        return data.get(\"value\")\n\n    class _ToolCallable:\n        \"\"\"Invokes one host-side tool via the loopback HTTP bridge.\"\"\"\n\n        __slots__ = (\"_name\",)\n\n        def __init__(self, name: str):\n            self._name = name\n\n        def __repr__(self) -> str:\n            return f\"<tool.{self._name}>\"\n\n        def __call__(self, args=None, /, **kwargs):\n            if args is None:\n                merged: dict = {}\n            elif isinstance(args, dict):\n                merged = dict(args)","sourceCodeStart":401,"sourceCodeEnd":437,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/eval/py/prelude.py#L401-L437","documentation":"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.","triggerScenarios":"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}`).","commonSituations":"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.","solutions":["Inspect the tool name and arguments — try a known-good call (e.g. a simple read) to distinguish 'this call failed' from 'bridge broken'.","Verify the tool name exists in the current session's tool set (names may have changed between versions).","Check the host/agent logs for the underlying tool failure that produced the empty error.","Retry if the failure was transient (e.g. a command that timed out)."],"exampleFix":"// before\nresult = tool.bash({\"command\": \"make test\"})\n\n// after\ntry:\n    result = tool.bash({\"command\": \"make test\"})\nexcept RuntimeError as e:\n    if \"failed\" in str(e) and len(str(e)) < 40:\n        print(f\"tool.bash failed without details; check host logs\")\n    raise","handlingStrategy":"try-catch","validationCode":"# no reliable pre-check; validate tool name against the session's tool list if exposed\n# and verify bridge protocol version matches the prelude","typeGuard":null,"tryCatchPattern":"try:\n    result = tool.bash({\"command\": cmd})\nexcept RuntimeError as e:\n    msg = str(e)\n    if msg.endswith(\"failed\"):\n        print(f\"tool failed with no server message; check host logs\")\n    raise","preventionTips":["Confirm tool names against the current session's tool set — names change between versions.","Keep the prelude and host agent on matching versions (protocol is `{ok, value, error}`).","Wrap individual tool calls so one failed call doesn't abort the whole eval script.","Check host/agent logs when the error message is the generic fallback — the real cause lives there."],"tags":["python","ipc","http","rpc","eval"],"backgroundTag":"rpc-call-failed","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}