unclecode/crawl4ai · error · HTTPException
e.response.text
Error message
e.response.text
What it means
In deploy/docker/mcp_bridge.py each proxied MCP tool call forwards to the FastAPI service over httpx; when the upstream returns 4xx/5xx, raise_for_status() raises httpx.HTTPStatusError and the bridge re-raises HTTPException(e.response.status_code, e.response.text). So this 'error' is a faithful passthrough: the status code and body are the upstream FastAPI error (its detail JSON), not generated by the bridge.
Source
Thrown at deploy/docker/mcp_bridge.py:79
placeholder = "{" + k + "}"
if placeholder in path:
path = path.replace(placeholder, str(v))
kwargs.pop(k)
url = base_url.rstrip("/") + path
headers = _service_auth_headers()
async with httpx.AsyncClient(timeout=timeout) as client:
try:
r = (
await client.get(url, params=kwargs, headers=headers)
if method == "GET"
else await client.request(method, url, json=kwargs, headers=headers)
)
r.raise_for_status()
return r.text if method == "GET" else r.json()
except httpx.HTTPStatusError as e:
# surface FastAPI error details instead of plain 500
raise HTTPException(e.response.status_code, e.response.text)
except httpx.TimeoutException:
raise HTTPException(504, "upstream request timed out")
return proxy
# ── main entry point ────────────────────────────────────────────
def attach_mcp(
app: FastAPI,
*, # keyword‑only
base: str = "/mcp",
name: str | None = None,
base_url: str, # eg. "http://127.0.0.1:8020"
timeout: float | None = None, # httpx timeout in seconds; None = no limit
) -> None:
"""Call once after all routes are declared to expose WS+SSE MCP endpoints."""
server_name = name or app.title or "FastAPI-MCP"
mcp = Server(server_name)
# tools: Dict[str, Callable] = {}View on GitHub (pinned to 7e80152142)
Solutions
- Parse e.response.text (or the MCP error payload's detail) — it is the upstream FastAPI error JSON; fix the argument per that message.
- Verify service auth configuration between the bridge and the base_url service if codes are 401/403.
- Hit the underlying HTTP endpoint directly with curl to confirm behavior independent of MCP.
- For persistent 5xx, check the upstream service logs — the bridge only mirrors them.
Example fix
# before
tools/call {"name": "monitor_health", "arguments": {}} # -> error 500, detail 'Monitor not initialized'
# after (initialize monitor / start upstream fully, then retry)
tools/call {"name": "monitor_health", "arguments": {}} # -> 200 payload Defensive patterns
Strategy: try-catch
Try / catch
# MCP tools/call returns error payloads, not exceptions:
if isinstance(result_text, str) and result_text.startswith('{"error"'):
err = json.loads(result_text)
if err["error"] in (400, 422):
fix_arguments_per_detail(err["detail"])
elif err["error"] in (401, 403):
fix_service_auth()
elif err["error"] >= 500:
check_upstream_logs() Prevention
- Treat the bridge as a passthrough: debug the upstream endpoint directly with curl.
- Keep service auth credentials in sync between bridge and upstream.
- Handle the {error, detail} JSON shape in MCP client code rather than string-matching.
When it happens
Trigger: Calling an MCP tool whose underlying HTTP endpoint fails — e.g. crawl tool with an invalid URL (upstream 400), unauthorized service auth (401/403), monitor endpoints before initialization (upstream 500), any upstream validation failure.
Common situations: Debugging via MCP client and seeing raw upstream detail text; service-to-service auth headers (_service_auth_headers) missing or expired so every proxied call 401s; upstream schema changes making previously valid tool arguments invalid.
Related errors
- upstream request timed out
- tool not found
- resource not found
- [NSTProxy] API Error: {data.get('msg', 'Unknown error')}
- [NSTProxy] Invalid API response — expected a non-empty list
AI-assisted analysis of unclecode/crawl4ai@7e80152142 (2026-08-14).
Data as JSON: /api/errors/6a99e7d2b90035ea.
Report an issue: GitHub.