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

  1. Parse e.response.text (or the MCP error payload's detail) — it is the upstream FastAPI error JSON; fix the argument per that message.
  2. Verify service auth configuration between the bridge and the base_url service if codes are 401/403.
  3. Hit the underlying HTTP endpoint directly with curl to confirm behavior independent of MCP.
  4. 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

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


AI-assisted analysis of unclecode/crawl4ai@7e80152142 (2026-08-14). Data as JSON: /api/errors/6a99e7d2b90035ea. Report an issue: GitHub.