abhigyanpatwari/GitNexus · error

Invalid group resource URI (expected gitnexus://group/{name}

Error message

Invalid group resource URI (expected gitnexus://group/{name}/contracts or .../status): ${uri}

What it means

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.

Source

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

  let u: URL;
  try {
    u = new URL(uri);
  } catch {
    throw new Error(`Unknown resource URI: ${uri}`);
  }

  if (u.protocol !== 'gitnexus:') {
    throw new Error(`Unknown resource URI: ${uri}`);
  }

  if (u.hostname === 'group') {
    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 = {};

View on GitHub (pinned to 0d1aed942f)

Solutions

  1. Provide both parts: gitnexus://group/{groupName}/contracts or gitnexus://group/{groupName}/status.
  2. Guard template builds so an empty group name fails before the call rather than producing a malformed URI.
  3. To discover what exists, list resources from the server instead of guessing group URIs.

Example fix

// before
const uri = `gitnexus://group/${group}/contracts`; // group = '' -> 'gitnexus://group//contracts' collapses to 1 segment... ensure group non-empty

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

Strategy: validation

Validate before calling

function buildGroupUri(group: string, leaf: 'contracts' | 'status'): string {
  const segments = group.split('/').map((s) => encodeURIComponent(s)).filter((s) => s.length > 0);
  if (segments.length === 0) throw new RangeError('group name required');
  return `gitnexus://group/${segments.join('/')}/${leaf}`;
}

Type guard

const isWellFormedGroupUri = (uri: string): boolean => {
  try {
    const u = new URL(uri);
    return u.protocol === 'gitnexus:' && u.hostname === 'group' &&
      u.pathname.replace(/^\/+|\/+$/g, '').split('/').filter(Boolean).length >= 2;
  } catch { return false; }
};

Try / catch

try {
  await client.readResource({ uri });
} catch (e) {
  if (e instanceof Error && /Invalid group resource URI \(expected/.test(e.message)) {
    throw new Error(`Group URI needs both name and leaf: gitnexus://group/{name}/contracts|status — got ${uri}`);
  }
  throw e;
}

Prevention

When it happens

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

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

Related errors


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