rohitg00/ai-engineering-from-scratch · error · ValueError

unknown resource

Error message

unknown resource

What it means

The uri passed to resources/read is a string but is not a key in the server's in-memory self.resources table. The simulator registers a fixed set of study:// URIs at construction; anything else — http:// URLs, typos, or URIs listed by a different server instance — is rejected. List valid URIs first via resources/list to see what this instance serves.

Source

Thrown at certifications/claude/lessons/11-mcp-server-design-and-integration/code/main.py:270

            return self._complete(
                tools=tools, ttlMs=300_000, cacheScope="public"
            ), []
        if method == "tools/call":
            return self._call_tool(params, metadata)
        if method == "resources/list":
            resources = [
                {"uri": uri, "name": uri.removeprefix("config://")}
                for uri in sorted(self.resources)
            ]
            return self._complete(
                resources=resources, ttlMs=60_000, cacheScope="private"
            ), []
        if method == "resources/read":
            uri = params["uri"]
            if not isinstance(uri, str):
                raise ValueError("uri must be a string")
            if uri not in self.resources:
                raise ValueError("unknown resource")
            return self._complete(
                contents=[
                    {
                        "uri": uri,
                        "mimeType": "application/json",
                        "text": self.resources[uri],
                    }
                ],
                ttlMs=30_000,
                cacheScope="private",
            ), []
        if method == "prompts/list":
            prompts = [
                {"name": name, "description": self.prompts[name]}
                for name in sorted(self.prompts)
            ]
            return self._complete(
                prompts=prompts, ttlMs=300_000, cacheScope="public"

View on GitHub (pinned to 39ea8a1c6d)

Solutions

  1. Call resources/list (or read server state) and use an exact returned URI
  2. Compare strings byte-for-byte — trailing slashes and case differences matter since this is a plain dict lookup
  3. Derive URIs dynamically from the list response instead of hardcoding them

Example fix

# before
server.exchange("resources/read", {"uri": "study://catalog/", "_meta": meta})
# after
listed = server.exchange("resources/list", {"_meta": meta})[0]
uri = listed["resources"][0]["uri"]
server.exchange("resources/read", {"uri": uri, "_meta": meta})
Defensive patterns

Strategy: validation

Validate before calling

listed = server.exchange("resources/list", {"_meta": meta})[0]
known = {r["uri"] for r in listed["resources"]}
if uri not in known:
    raise LookupError(f"unknown resource {uri!r}; known: {sorted(known)}")

Type guard

def uri_exists(server, uri: str) -> bool:
    return uri in getattr(server, "resources", {})

Try / catch

try:
    server.exchange("resources/read", params)
except ValueError as e:
    if str(e) == "unknown resource":
        params["uri"] = pick_from_resources_list()  # reselect and retry once
    else:
        raise

Prevention

When it happens

Trigger: Reading "study://catalog/typo" when the table has "study://catalog"; hardcoding a URI from an older server version whose registry changed; sending an https:// URL to a server that only serves study:// resources.

Common situations: Stale hardcoded URI lists after server updates; environment differences (dev server registers different resources than prod); copy-pasting example URIs from docs that do not match this deployment.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


AI-assisted analysis of rohitg00/ai-engineering-from-scratch@39ea8a1c6d (2026-08-26). Data as JSON: /api/errors/b3ab86a16c20e629. Report an issue: GitHub.