abhigyanpatwari/GitNexus · error

Invalid group resource URI (empty group name): ${uri}

Error message

Invalid group resource URI (empty group name): ${uri}

What it means

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.

Source

Thrown at gitnexus/src/mcp/resources.ts:196

    const segments = u.pathname
      .replace(/^\/+|\/+$/g, '')
      .split('/')
      .filter(Boolean);
    if (segments.length < 2) {
      throw new Error(
        `Invalid group resource URI (expected gitnexus://group/{name}/contracts or .../status): ${uri}`,
      );
    }
    const tail = segments[segments.length - 1]!;
    if (tail !== 'contracts' && tail !== 'status') {
      throw new Error(`Unknown group resource path in URI: ${uri}`);
    }
    const groupName = segments
      .slice(0, -1)
      .map((s) => decodeURIComponent(s))
      .join('/');
    if (!groupName) {
      throw new Error(`Invalid group resource URI (empty group name): ${uri}`);
    }
    if (tail === 'status') {
      return { kind: 'group', groupName, resourceType: 'status' };
    }
    const contractsFilter: GroupContractsResourceFilter = {};
    const type = u.searchParams.get('type');
    if (type && type.trim()) contractsFilter.type = type.trim();
    const repo = u.searchParams.get('repo');
    if (repo && repo.trim()) contractsFilter.repo = repo.trim();
    if (u.searchParams.has('unmatchedOnly')) {
      const coerced = parseUnmatchedOnlyParam(u.searchParams.get('unmatchedOnly'));
      if (coerced !== undefined) contractsFilter.unmatchedOnly = coerced;
    }
    return { kind: 'group', groupName, resourceType: 'contracts', contractsFilter };
  }

  if (u.hostname === 'repo') {
    const segments = u.pathname

View on GitHub (pinned to 0d1aed942f)

Solutions

  1. Include a real, non-empty group name: gitnexus://group/my-group/contracts.
  2. Build URIs with encodeURIComponent(groupName) and reject empty names client-side before composing.
  3. If you see this repeatedly, audit the code that generates resource URIs for decode/re-encode loops.

Example fix

// before
const uri = `gitnexus://group/${rawName}/contracts`; // rawName decodes to ''

// after
if (!rawName || !decodeURIComponent(rawName)) throw new RangeError('group name required');
const uri = `gitnexus://group/${encodeURIComponent(rawName)}/contracts`;
Defensive patterns

Strategy: validation

Validate before calling

function buildGroupUri(group: string, leaf: 'contracts' | 'status'): string {
  if (!group || decodeURIComponent(group).trim() === '') {
    throw new RangeError('group name must decode to a non-empty string');
  }
  return `gitnexus://group/${encodeURIComponent(group)}/${leaf}`;
}

Type guard

const hasNonEmptyGroupName = (group: string): boolean =>
  group.length > 0 && decodeURIComponent(group).length > 0;

Try / catch

try {
  await client.readResource({ uri });
} catch (e) {
  if (e instanceof Error && /empty group name/.test(e.message)) {
    throw new Error(`Group name decoded to empty — check URI generation for ${uri}`);
  }
  throw e;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of abhigyanpatwari/GitNexus@0d1aed942f (2026-08-20). Data as JSON: /api/errors/3b417d7183f4624e. Report an issue: GitHub.