abhigyanpatwari/GitNexus · error · Error

links[${i}].to "${link.to}" does not match any repo path in

Error message

links[${i}].to "${link.to}" does not match any repo path in group

What it means

Thrown during links[] validation when a link's 'to' field is missing or not present in the repoPaths set derived from the repos mapping keys. Symmetric with the 'from' check (error 147): both endpoints of every link must reference declared repos.

Source

Thrown at gitnexus/src/core/group/config-parser.ts:72

  if (raw.version !== 1) {
    throw new Error(`Unsupported group.yaml version: ${raw.version}. Expected 1.`);
  }
  if (!raw.name || typeof raw.name !== 'string') throw new Error('name is required in group.yaml');
  if (!raw.repos || typeof raw.repos !== 'object' || Array.isArray(raw.repos)) {
    throw new Error('repos is required in group.yaml (must be a mapping)');
  }

  const repos = raw.repos as Record<string, string>;
  const repoPaths = new Set(Object.keys(repos));

  const rawLinks = (raw.links as unknown[]) || [];
  const links: GroupManifestLink[] = rawLinks.map((l: unknown, i: number) => {
    const link = l as Record<string, unknown>;
    if (!link.from || !repoPaths.has(link.from as string)) {
      throw new Error(`links[${i}].from "${link.from}" does not match any repo path in group`);
    }
    if (!link.to || !repoPaths.has(link.to as string)) {
      throw new Error(`links[${i}].to "${link.to}" does not match any repo path in group`);
    }
    if (!VALID_CONTRACT_TYPES.includes(link.type as ContractType)) {
      throw new Error(
        `links[${i}].type "${link.type}" is invalid. Expected: ${VALID_CONTRACT_TYPES.join(', ')}`,
      );
    }
    if (!VALID_ROLES.includes(link.role as ContractRole)) {
      throw new Error(`links[${i}].role "${link.role}" is invalid. Expected: provider | consumer`);
    }
    if (
      link.contract === undefined ||
      link.contract === null ||
      String(link.contract).trim() === ''
    ) {
      throw new Error(`links[${i}].contract is required`);
    }
    return {
      from: link.from as string,

View on GitHub (pinned to d540b00184)

Solutions

  1. Compare link.to verbatim against the repos mapping keys.
  2. Add the missing repo to repos, or fix the link.to path to match an existing key.
  3. Use the index i from the message to find the offending entry.

Example fix

# before — 'to' repo not declared
repos:
  services/api: ./services/api
links:
  - { from: services/api, to: services/missing, type: http, contract: GET /v1, role: provider }

# after — declare the missing repo
repos:
  services/api: ./services/api
  services/missing: ./services/missing
links:
  - { from: services/api, to: services/missing, type: http, contract: GET /v1, role: provider }
Defensive patterns

Strategy: validation

Validate before calling

function validateLinksTo(raw: Record<string, unknown>): string[] {
  const repoPaths = new Set(Object.keys(raw.repos as Record<string, string>));
  const errs: string[] = [];
  ((raw.links as unknown[]) || []).forEach((l, i) => {
    const link = l as Record<string, unknown>;
    if (typeof link.to !== 'string' || !repoPaths.has(link.to)) {
      errs.push(`links[${i}].to "${String(link.to)}" not in repos`);
    }
  });
  return errs;
}

Prevention

When it happens

Trigger: A link whose 'to' references a repo path not in repos; a link missing the 'to' field; a path-convention mismatch between the link and the repos key.

Common situations: Same as 147: inconsistent path prefixes, repo renamed in one place but not the other, or a stale link from a previous group config.

Related errors


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