Skip to content

Commit 27d7d7c

Browse files
committed
fix(navigate): raise on timeout instead of returning a soft error dict
navigate's docstring promised "Raises on timeout" but the body returned {"error": ..., "_timeout": true}. MCP clients saw a successful tool call carrying an error payload, so agents kept driving a tab that had never loaded — one burned its whole budget looping extract_markdown on a blank page after a 30s timeout. Raise TimeoutError so the failure surfaces as a real tool error, and say in the message that the tab is alive but unusable, with the recovery options. Matches the raise ValueError convention used elsewhere in the module. No other caller consumed the _timeout sentinel.
1 parent 1f7f4f8 commit 27d7d7c

1 file changed

Lines changed: 5 additions & 1 deletion

File tree

‎src/umbra/server.py‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -776,7 +776,11 @@ async def navigate(tab_id: str, url: str, timeout_s: float = 30.0) -> dict[str,
776776
try:
777777
await asyncio.wait_for(tab.get(url), timeout=timeout_s)
778778
except asyncio.TimeoutError:
779-
return _compact({"url": url, "error": f"timeout after {timeout_s}s", "_timeout": True})
779+
raise TimeoutError(
780+
f"navigate({tab_id!r}, {url!r}) timed out after {timeout_s}s — page never finished loading. "
781+
f"The tab is still alive but shows no usable content: do NOT extract/read from it. "
782+
f"Retry with a longer timeout_s, try a different URL, or abort this path."
783+
) from None
780784
return _compact({"url": url})
781785

782786

0 commit comments

Comments
 (0)