abhigyanpatwari/GitNexus · error · Error

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

Error message

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

What it means

Thrown during links[] validation when a link's 'from' field is missing or does not match any key in the parsed 'repos' mapping. Every link must connect two repos that are declared in repos, so the parser builds a repoPaths set from repos' keys and checks each link endpoint against it. The index i and the offending value are included.

Source

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

  }

  if (raw.version === undefined) throw new Error('version is required in group.yaml');
  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`);

View on GitHub (pinned to d540b00184)

Solutions

  1. Compare the link.from value verbatim against the keys in the repos mapping — they must match exactly (including leading './' or trailing slash).
  2. Add the missing repo to repos, or correct the path in the link to point at an existing repo key.
  3. Use the index i from the message to locate the exact offending link entry.

Example fix

# before — from uses ./services/api but repos key is services/api
repos:
  services/api: ./services/api
links:
  - { from: ./services/api, to: services/worker, type: http, contract: GET /v1, role: provider }

# after — keys match exactly
repos:
  services/api: ./services/api
links:
  - { from: services/api, to: services/worker, type: http, contract: GET /v1, role: provider }
Defensive patterns

Strategy: validation

Validate before calling

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

Prevention

When it happens

Trigger: A link with from: './services/api' when the repos mapping key is 'services/api' (path-prefix mismatch); a link referencing a repo that was never added to repos; a link missing the 'from' field entirely.

Common situations: Inconsistent path conventions (leading './' in one place but not the other); a repo renamed in repos but not in links; a link copy-pasted from another group without updating its endpoints.

Related errors


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