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
- List first: resources/read must use a name verbatim from resources/list.
- Re-list resources after any server redeploy.
- 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
- Refresh resources/list after every redeploy.
- Strip whitespace from names sourced via copy-paste.
- Register resource providers before attach_mcp().
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
- tool not found
- e.response.text
- [NSTProxy] API Error: {data.get('msg', 'Unknown error')}
- [NSTProxy] Invalid API response — expected a non-empty list
- Task not found
AI-assisted analysis of unclecode/crawl4ai@7e80152142 (2026-08-14).
Data as JSON: /api/errors/2443119076f6e067.
Report an issue: GitHub.