unclecode/crawl4ai · error · HTTPException

resource not found

Error message

resource not found

What it means

The MCP bridge's read_resource handler raises HTTPException(404, 'resource not found') when the requested resource name is absent from the resources registry populated at attach_mcp time. Valid names are exactly those returned by resources/list.

Source

Thrown at deploy/docker/mcp_bridge.py:170

        try:
            res = await proxy(**(arguments or {}))
        except HTTPException as exc:
            # map server‑side errors into MCP "text/error" payloads
            err = {"error": exc.status_code, "detail": exc.detail}
            return [t.TextContent(type = "text", text=json.dumps(err, ensure_ascii=False))]
        return [t.TextContent(type = "text", text=json.dumps(res, default=str, ensure_ascii=False))]

    @mcp.list_resources()
    async def _list_resources() -> List[t.Resource]:
        return [
            t.Resource(name=k, description=inspect.getdoc(f) or "", mime_type="application/json")
            for k, f in resources.items()
        ]

    @mcp.read_resource()
    async def _read_resource(name: str) -> List[t.TextContent]:
        if name not in resources:
            raise HTTPException(404, "resource not found")
        res = resources[name]()
        return [t.TextContent(type = "text", text=json.dumps(res, default=str, ensure_ascii=False))]

    @mcp.list_resource_templates()
    async def _list_templates() -> List[t.ResourceTemplate]:
        return [
            t.ResourceTemplate(
                name=k,
                description=inspect.getdoc(f) or "",
                parameters={
                    p: {"type": "string"} for p in _path_params(app, f)
                },
            )
            for k, f in templates.items()
        ]

    init_opts = InitializationOptions(
        server_name=server_name,

View on GitHub (pinned to 7e80152142)

Solutions

  1. List first: resources/read must use a name verbatim from resources/list.
  2. Re-list resources after any server redeploy.
  3. Register resource providers before attach_mcp() so they appear in the registry.

Example fix

# before
resources/read {"name": " stats "}

# after
resources/list -> ["stats"]
resources/read {"name": "stats"}
Defensive patterns

Strategy: validation

Validate before calling

available = [r.name for r in (await session.list_resources()).resources]
if resource_name not in available:
    raise ValueError(f"resource {resource_name!r} not in {available}")

Type guard

def is_known_resource(name, advertised) -> bool:
    return isinstance(name, str) and name in advertised

Try / catch

result = await session.read_resource(resource_name)
# bridge raises HTTPException(404, 'resource not found'); client sees it as an error response:
except ResourceError as e:
    if "resource not found" in str(e):
        advertised = await session.list_resources()
        raise KeyError(f"{resource_name!r} not in {[r.name for r in advertised]}") from e

Prevention

When it happens

Trigger: Calling resources/read with a mistyped or stale resource name; reading a resource whose backing function was registered after attach_mcp; client holding a cached resource list from a previous server build.

Common situations: Version skew between MCP client cache and server; renames of resource-backed endpoints; trailing whitespace in names from copy-paste.

Related errors


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