{"record":{"id":"ea65757fedfdc9de","repo":"Graphify-Labs/graphify","slug":"unknown-resource-uri-str","errorCode":null,"errorMessage":"Unknown resource: {uri_str}","messagePattern":"Unknown resource: (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"graphify/serve.py","lineNumber":1973,"sourceCode":"                f\"AMBIGUOUS: {confs.count('AMBIGUOUS')} ({round(confs.count('AMBIGUOUS')/total*100)}%)\\n\"\n            )\n        if uri_str == \"graphify://questions\":\n            try:\n                from graphify.analyze import suggest_questions\n                community_labels = _load_community_labels()\n                questions = suggest_questions(G, communities, community_labels, top_n=10)\n                if not questions:\n                    return \"No suggested questions available.\"\n                lines = [\"Suggested questions:\"]\n                for q in questions:\n                    if isinstance(q, dict):\n                        lines.append(f\"  - {q.get('question', '')}\")\n                    else:\n                        lines.append(f\"  - {q}\")\n                return \"\\n\".join(lines)\n            except Exception as exc:\n                return f\"Could not generate questions: {exc}\"\n        raise ValueError(f\"Unknown resource: {uri_str}\")\n\n    async def call_tool(name: str, arguments: dict) -> list[types.TextContent]:\n        arguments = dict(arguments or {})\n        project_path = arguments.pop(\"project_path\", None)\n        handler = _handlers.get(name)\n        if not handler:\n            return [types.TextContent(type=\"text\", text=f\"Unknown tool: {name}\")]\n        try:\n            _select_graph(project_path)  # bind G/communities to the target graph\n            return [types.TextContent(type=\"text\", text=handler(arguments))]\n        except Exception as exc:\n            return [types.TextContent(type=\"text\", text=f\"Error executing {name}: {exc}\")]\n\n    if hasattr(Server, \"list_tools\"):\n        # mcp 1.x: decorator-based registration. The SDK wraps the raw returns\n        # (list[Tool] -> ListToolsResult, str -> resource contents) itself.\n        server = Server(\"graphify\")\n        server.list_tools()(list_tools)","sourceCodeStart":1955,"sourceCodeEnd":1991,"githubUrl":"https://github.com/Graphify-Labs/graphify/blob/7fe58b0b0f3873be9a21c30106b8b8527c353aa6/graphify/serve.py#L1955-L1991","documentation":"Raised at the tail of the MCP read_resource handler (graphify/serve.py) when a client reads a resource whose uri_str matched none of the handled resource schemes/templates. Every recognized resource returns early; falling through to the final raise means the URI is outside the server's resource namespace.","triggerScenarios":"An MCP client calls read_resource with an unknown URI — a mistyped path, a scheme the server does not host (e.g. graphify://graph vs whatever templates are registered), or a resource removed in this version. Note: unlike call_tool, read_resource lets the ValueError propagate rather than returning a soft error text.","commonSituations":"Hand-written MCP client configs referencing resource URIs guessed from docs of a different graphify version; stale clients after a server upgrade renamed/removed resources; URI typos or missing encoding.","solutions":["List the server's actual resources first (MCP resources/list) and use a URI it returns verbatim.","Match the scheme and path layout the server registers; do not invent graphify:// URIs from memory.","After upgrading graphify, re-check the resource list for renames or removals.","As a client, catch this ValueError on read_resource and show the URI to the user for correction."],"exampleFix":"# before\nawait session.read_resource(\"graphify://unknown/thing\")\n\n# after\nresources = await session.list_resources()\nuri = next(r.uri for r in resources if \"questions\" in str(r.uri))\nresult = await session.read_resource(uri)","handlingStrategy":"validation","validationCode":"# discover real URIs before reading\nresources = await session.list_resources()\nvalid_uris = {str(r.uri) for r in resources}\nassert str(want_uri) in valid_uris, f\"unknown resource {want_uri}; have {sorted(valid_uris)}\"","typeGuard":"def is_known_resource(uri: str, listed: set[str]) -> bool:\n    return uri in listed","tryCatchPattern":"try:\n    result = await session.read_resource(uri)\nexcept ValueError as e:\n    if str(e).startswith(\"Unknown resource\"):\n        listed = await session.list_resources()\n        return error_to_user(f\"{uri} not hosted; available: {[str(r.uri) for r in listed]}\")\n    raise","preventionTips":["Always enumerate resources/list first and use returned URIs verbatim.","Re-enumerate after upgrading graphify to catch renamed resources.","Never hand-construct resource URIs from memory or old docs."],"tags":["mcp","resources","validation"],"backgroundTag":null,"analyzedSha":"7fe58b0b0f3873be9a21c30106b8b8527c353aa6","analyzedAt":"2026-08-14T19:23:21.323Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}