{"record":{"id":"b3ab86a16c20e629","repo":"rohitg00/ai-engineering-from-scratch","slug":"unknown-resource","errorCode":null,"errorMessage":"unknown resource","messagePattern":"unknown resource","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"certifications/claude/lessons/11-mcp-server-design-and-integration/code/main.py","lineNumber":270,"sourceCode":"            return self._complete(\n                tools=tools, ttlMs=300_000, cacheScope=\"public\"\n            ), []\n        if method == \"tools/call\":\n            return self._call_tool(params, metadata)\n        if method == \"resources/list\":\n            resources = [\n                {\"uri\": uri, \"name\": uri.removeprefix(\"config://\")}\n                for uri in sorted(self.resources)\n            ]\n            return self._complete(\n                resources=resources, ttlMs=60_000, cacheScope=\"private\"\n            ), []\n        if method == \"resources/read\":\n            uri = params[\"uri\"]\n            if not isinstance(uri, str):\n                raise ValueError(\"uri must be a string\")\n            if uri not in self.resources:\n                raise ValueError(\"unknown resource\")\n            return self._complete(\n                contents=[\n                    {\n                        \"uri\": uri,\n                        \"mimeType\": \"application/json\",\n                        \"text\": self.resources[uri],\n                    }\n                ],\n                ttlMs=30_000,\n                cacheScope=\"private\",\n            ), []\n        if method == \"prompts/list\":\n            prompts = [\n                {\"name\": name, \"description\": self.prompts[name]}\n                for name in sorted(self.prompts)\n            ]\n            return self._complete(\n                prompts=prompts, ttlMs=300_000, cacheScope=\"public\"","sourceCodeStart":252,"sourceCodeEnd":288,"githubUrl":"https://github.com/rohitg00/ai-engineering-from-scratch/blob/39ea8a1c6d0b61f071226eff7ede4d4105fed820/certifications/claude/lessons/11-mcp-server-design-and-integration/code/main.py#L252-L288","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Call resources/list (or read server state) and use an exact returned URI","Compare strings byte-for-byte — trailing slashes and case differences matter since this is a plain dict lookup","Derive URIs dynamically from the list response instead of hardcoding them"],"exampleFix":"# before\nserver.exchange(\"resources/read\", {\"uri\": \"study://catalog/\", \"_meta\": meta})\n# after\nlisted = server.exchange(\"resources/list\", {\"_meta\": meta})[0]\nuri = listed[\"resources\"][0][\"uri\"]\nserver.exchange(\"resources/read\", {\"uri\": uri, \"_meta\": meta})","handlingStrategy":"validation","validationCode":"listed = server.exchange(\"resources/list\", {\"_meta\": meta})[0]\nknown = {r[\"uri\"] for r in listed[\"resources\"]}\nif uri not in known:\n    raise LookupError(f\"unknown resource {uri!r}; known: {sorted(known)}\")","typeGuard":"def uri_exists(server, uri: str) -> bool:\n    return uri in getattr(server, \"resources\", {})","tryCatchPattern":"try:\n    server.exchange(\"resources/read\", params)\nexcept ValueError as e:\n    if str(e) == \"unknown resource\":\n        params[\"uri\"] = pick_from_resources_list()  # reselect and retry once\n    else:\n        raise","preventionTips":["Never hardcode URIs; source them from resources/list at runtime","Log the server's listed URIs on startup so drift is visible immediately","Byte-compare URIs when debugging — trailing slashes and case are significant"],"tags":["mcp","resources","unknown-uri","lookup"],"backgroundTag":"resource-not-found","analyzedSha":"39ea8a1c6d0b61f071226eff7ede4d4105fed820","analyzedAt":"2026-08-26T03:13:46.626Z","schemaVersion":2},"datasetVersion":"2026-08-26T07:17:17.940Z"}