{"record":{"id":"afad4ee0b682bb5a","repo":"abhigyanpatwari/GitNexus","slug":"invalid-group-resource-uri-expected-gitnexus-gr","errorCode":null,"errorMessage":"Invalid group resource URI (expected gitnexus://group/{name}/contracts or .../status): ${uri}","messagePattern":"Invalid group resource URI \\(expected gitnexus://group/(.+?)/contracts or \\.\\.\\./status\\): (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"gitnexus/src/mcp/resources.ts","lineNumber":183,"sourceCode":"\n  let u: URL;\n  try {\n    u = new URL(uri);\n  } catch {\n    throw new Error(`Unknown resource URI: ${uri}`);\n  }\n\n  if (u.protocol !== 'gitnexus:') {\n    throw new Error(`Unknown resource URI: ${uri}`);\n  }\n\n  if (u.hostname === 'group') {\n    const segments = u.pathname\n      .replace(/^\\/+|\\/+$/g, '')\n      .split('/')\n      .filter(Boolean);\n    if (segments.length < 2) {\n      throw new Error(\n        `Invalid group resource URI (expected gitnexus://group/{name}/contracts or .../status): ${uri}`,\n      );\n    }\n    const tail = segments[segments.length - 1]!;\n    if (tail !== 'contracts' && tail !== 'status') {\n      throw new Error(`Unknown group resource path in URI: ${uri}`);\n    }\n    const groupName = segments\n      .slice(0, -1)\n      .map((s) => decodeURIComponent(s))\n      .join('/');\n    if (!groupName) {\n      throw new Error(`Invalid group resource URI (empty group name): ${uri}`);\n    }\n    if (tail === 'status') {\n      return { kind: 'group', groupName, resourceType: 'status' };\n    }\n    const contractsFilter: GroupContractsResourceFilter = {};","sourceCodeStart":165,"sourceCodeEnd":201,"githubUrl":"https://github.com/abhigyanpatwari/GitNexus/blob/0d1aed942f0e8b5d3bac27519fff441aceea722d/gitnexus/src/mcp/resources.ts#L165-L201","documentation":"Thrown by parseResourceUri for a gitnexus://group/... URI whose path contains fewer than two non-empty segments. Group resources require both a group name and a leaf segment (contracts or status), so 'gitnexus://group' (no segments) and 'gitnexus://group/contracts' (one segment — here 'contracts' is taken as the group name slot and the tail is missing) are both malformed.","triggerScenarios":"Reading 'gitnexus://group' or 'gitnexus://group/' (zero segments), or 'gitnexus://group/contracts' / 'gitnexus://group/status' (one segment — the leaf was supplied but the group name was omitted). Extra slashes are tolerated because segments are trimmed and empty ones filtered.","commonSituations":"URI templates filled with an empty group name, or users assuming 'gitnexus://group/contracts' lists contracts for all groups. Trailing-slash builds like `gitnexus://group/${group}/contracts` with group='' collapse to the one-segment form.","solutions":["Provide both parts: gitnexus://group/{groupName}/contracts or gitnexus://group/{groupName}/status.","Guard template builds so an empty group name fails before the call rather than producing a malformed URI.","To discover what exists, list resources from the server instead of guessing group URIs."],"exampleFix":"// before\nconst uri = `gitnexus://group/${group}/contracts`; // group = '' -> 'gitnexus://group//contracts' collapses to 1 segment... ensure group non-empty\n\n// after\nif (!group) throw new RangeError('group required');\nconst uri = `gitnexus://group/${encodeURIComponent(group)}/contracts`;","handlingStrategy":"validation","validationCode":"function buildGroupUri(group: string, leaf: 'contracts' | 'status'): string {\n  const segments = group.split('/').map((s) => encodeURIComponent(s)).filter((s) => s.length > 0);\n  if (segments.length === 0) throw new RangeError('group name required');\n  return `gitnexus://group/${segments.join('/')}/${leaf}`;\n}","typeGuard":"const isWellFormedGroupUri = (uri: string): boolean => {\n  try {\n    const u = new URL(uri);\n    return u.protocol === 'gitnexus:' && u.hostname === 'group' &&\n      u.pathname.replace(/^\\/+|\\/+$/g, '').split('/').filter(Boolean).length >= 2;\n  } catch { return false; }\n};","tryCatchPattern":"try {\n  await client.readResource({ uri });\n} catch (e) {\n  if (e instanceof Error && /Invalid group resource URI \\(expected/.test(e.message)) {\n    throw new Error(`Group URI needs both name and leaf: gitnexus://group/{name}/contracts|status — got ${uri}`);\n  }\n  throw e;\n}","preventionTips":["Always fill both slots: group name AND leaf (contracts or status).","Fail fast client-side when a template variable for the group name is empty.","Remember 'gitnexus://group/contracts' is NOT a list-all — it is a missing-name error."],"tags":["mcp","resources","uri-validation","group-routing"],"backgroundTag":"invalid-resource-uri","analyzedSha":"0d1aed942f0e8b5d3bac27519fff441aceea722d","analyzedAt":"2026-08-20T23:29:22.980Z","contentChangedAt":"2026-08-20T23:29:22.980Z","schemaVersion":2},"datasetVersion":"2026-09-08T20:17:18.057Z"}