{"record":{"id":"3b417d7183f4624e","repo":"abhigyanpatwari/GitNexus","slug":"invalid-group-resource-uri-empty-group-name-u","errorCode":null,"errorMessage":"Invalid group resource URI (empty group name): ${uri}","messagePattern":"Invalid group resource URI \\(empty group name\\): (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"gitnexus/src/mcp/resources.ts","lineNumber":196,"sourceCode":"    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 = {};\n    const type = u.searchParams.get('type');\n    if (type && type.trim()) contractsFilter.type = type.trim();\n    const repo = u.searchParams.get('repo');\n    if (repo && repo.trim()) contractsFilter.repo = repo.trim();\n    if (u.searchParams.has('unmatchedOnly')) {\n      const coerced = parseUnmatchedOnlyParam(u.searchParams.get('unmatchedOnly'));\n      if (coerced !== undefined) contractsFilter.unmatchedOnly = coerced;\n    }\n    return { kind: 'group', groupName, resourceType: 'contracts', contractsFilter };\n  }\n\n  if (u.hostname === 'repo') {\n    const segments = u.pathname","sourceCodeStart":178,"sourceCodeEnd":214,"githubUrl":"https://github.com/abhigyanpatwari/GitNexus/blob/0d1aed942f0e8b5d3bac27519fff441aceea722d/gitnexus/src/mcp/resources.ts#L178-L214","documentation":"Thrown by parseResourceUri for a group URI whose name portion percent-decodes to an empty string. After stripping the leaf segment, the remaining segments are decoded and joined with '/'; if the result is empty the URI has no usable group name. This is a defensive guard for degenerate encodings — ordinary empty segments are already filtered out before decoding.","triggerScenarios":"Group URIs where every non-leaf segment decodes to nothing — e.g. encodings that collapse to empty after decodeURIComponent. Practical cases are rare; most empty-name mistakes (gitnexus://group//contracts) collapse to one segment and fail the earlier 'Invalid group resource URI' check instead.","commonSituations":"Exotic percent-encoding from hand-built or machine-mangled URIs; double-encoding or encoding experiments that decode to empty content. Usually a sign the URI was assembled by untrusted string manipulation rather than a template.","solutions":["Include a real, non-empty group name: gitnexus://group/my-group/contracts.","Build URIs with encodeURIComponent(groupName) and reject empty names client-side before composing.","If you see this repeatedly, audit the code that generates resource URIs for decode/re-encode loops."],"exampleFix":"// before\nconst uri = `gitnexus://group/${rawName}/contracts`; // rawName decodes to ''\n\n// after\nif (!rawName || !decodeURIComponent(rawName)) throw new RangeError('group name required');\nconst uri = `gitnexus://group/${encodeURIComponent(rawName)}/contracts`;","handlingStrategy":"validation","validationCode":"function buildGroupUri(group: string, leaf: 'contracts' | 'status'): string {\n  if (!group || decodeURIComponent(group).trim() === '') {\n    throw new RangeError('group name must decode to a non-empty string');\n  }\n  return `gitnexus://group/${encodeURIComponent(group)}/${leaf}`;\n}","typeGuard":"const hasNonEmptyGroupName = (group: string): boolean =>\n  group.length > 0 && decodeURIComponent(group).length > 0;","tryCatchPattern":"try {\n  await client.readResource({ uri });\n} catch (e) {\n  if (e instanceof Error && /empty group name/.test(e.message)) {\n    throw new Error(`Group name decoded to empty — check URI generation for ${uri}`);\n  }\n  throw e;\n}","preventionTips":["Encode name segments once (encodeURIComponent) and never round-trip decode/re-encode them.","Validate that every dynamic URI segment is non-empty after decoding before composing the URI.","Treat repeated hits of this error as a URI-builder bug, not bad user input."],"tags":["mcp","resources","uri-validation","group-routing","percent-encoding"],"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"}