{"record":{"id":"7ac2c3573c9211d4","repo":"abhigyanpatwari/GitNexus","slug":"unknown-resource-uri","errorCode":null,"errorMessage":"Unknown resource: ${uri}","messagePattern":"Unknown resource: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"gitnexus/src/mcp/resources.ts","lineNumber":285,"sourceCode":"  }\n\n  const repoName = parsed.repoName;\n\n  switch (parsed.resourceType) {\n    case 'context':\n      return getContextResource(backend, repoName);\n    case 'clusters':\n      return getClustersResource(backend, repoName);\n    case 'processes':\n      return getProcessesResource(backend, repoName);\n    case 'schema':\n      return getSchemaResource();\n    case 'cluster':\n      return getClusterDetailResource(parsed.param!, backend, repoName);\n    case 'process':\n      return getProcessDetailResource(parsed.param!, backend, repoName);\n    default:\n      throw new Error(`Unknown resource: ${uri}`);\n  }\n}\n\n// ─── Resource Implementations ─────────────────────────────────────────\n\n/**\n * Repos resource — list all indexed repositories\n */\nasync function getReposResource(backend: LocalBackend): Promise<string> {\n  const repos = await backend.listRepos();\n\n  if (repos.length === 0) {\n    return 'repos: []\\n# No repositories indexed. Run: gitnexus analyze';\n  }\n\n  const lines: string[] = ['repos:'];\n  for (const repo of repos) {\n    lines.push(`  - name: \"${repo.name}\"`);","sourceCodeStart":267,"sourceCodeEnd":303,"githubUrl":"https://github.com/abhigyanpatwari/GitNexus/blob/0d1aed942f0e8b5d3bac27519fff441aceea722d/gitnexus/src/mcp/resources.ts#L267-L303","documentation":"Thrown by readResource's dispatch switch: the URI parsed to kind 'repo', but its resourceType (the joined remaining path after the repo name) is not one of the six known values — context, clusters, processes, schema, cluster (with param), process (with param). The default arm rejects everything else.","triggerScenarios":"resources/read with 'gitnexus://repo/{name}/symbols', 'gitnexus://repo/{name}/wiki', or any second segment outside the known set; also a version-skew case where a client requests a resource type that the running GitNexus version does not implement.","commonSituations":"An LLM MCP client hallucinating plausible-sounding resource names; clients written against an older/newer GitNexus whose resource set differs; copying a URI from documentation for a different edition.","solutions":["Restrict resourceType to context, clusters, processes, schema, cluster/{id}, process/{name}","Fetch resources/list on connect and only read URIs it advertises","Upgrade the gitnexus package and the client together to remove version skew"],"exampleFix":"// before\nconst uri = `gitnexus://repo/${repoName}/symbols`;\n\n// after\nconst uri = `gitnexus://repo/${repoName}/schema`;","handlingStrategy":"validation","validationCode":"const REPO_RESOURCE_TYPES = ['context', 'clusters', 'processes', 'schema'];\nfunction isKnownRepoResourceType(t) {\n  return REPO_RESOURCE_TYPES.includes(t) || t.startsWith('cluster/') || t.startsWith('process/');\n}","typeGuard":"function parseRepoUriSafe(uri) {\n  try {\n    const u = new URL(uri);\n    if (u.protocol !== 'gitnexus:' || u.hostname !== 'repo') return null;\n    const seg = u.pathname.replace(/^\\/+|\\/+$/g, '').split('/').filter(Boolean);\n    if (seg.length < 2) return null;\n    return { repoName: seg[0], resourceType: seg.slice(1).join('/') };\n  } catch { return null; }\n}","tryCatchPattern":"try { return await readResource(uri, backend); }\ncatch (e) {\n  if (e.message === `Unknown resource: ${uri}`) return fallbackToSchemaResource(); // degrade to a known-good resource\n  throw e;\n}","preventionTips":["Filter candidate URIs through isKnownRepoResourceType before reading","On MCP client startup, read resources/list and derive the allowed URI set from it","Log the exact URI with the failure so hallucinated names are visible in traces"],"tags":["mcp","resource-uri","dispatch","client-error"],"backgroundTag":"unknown-resource-type","analyzedSha":"0d1aed942f0e8b5d3bac27519fff441aceea722d","analyzedAt":"2026-08-20T23:29:22.980Z","contentChangedAt":"2026-08-20T23:29:22.980Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}