abhigyanpatwari/GitNexus · error
Repository "${repoParam}" not found. Available: ${labels.joi
Error message
Repository "${repoParam}" not found. Available: ${labels.join(', ')} What it means
Repo resolution failed for a caller-supplied repoParam even after refreshing the registry, and at least one other repo IS indexed — so the error enumerates the available handles as a disambiguated list (#829): when two handles share a name, each label is annotated with its repoPath so the caller can pick correctly.
Source
Thrown at gitnexus/src/mcp/local/local-backend.ts:1742
if (this.repos.size === 0) {
throw new Error('No indexed repositories. Run: gitnexus analyze');
}
// Build a disambiguated "Available: …" list (#829). When two handles
// share a name, annotate each colliding label with its path so the
// caller can actually pick the right one. Single-name entries render
// identically to pre-#829 output.
const nameCounts = new Map<string, number>();
for (const h of this.repos.values()) {
const key = h.name.toLowerCase();
nameCounts.set(key, (nameCounts.get(key) ?? 0) + 1);
}
const labels = [...this.repos.values()].map((h) =>
(nameCounts.get(h.name.toLowerCase()) ?? 0) > 1 ? `${h.name} (${h.repoPath})` : h.name,
);
if (repoParam) {
throw new Error(`Repository "${repoParam}" not found. Available: ${labels.join(', ')}`);
}
throw new Error(
`Multiple repositories indexed. Specify which one with the "repo" parameter. Available: ${labels.join(', ')}`,
);
}
/**
* Re-point a resolved repo handle at a specific branch index (#2106).
*
* - No `branch` (default) → the flat workspace handle, unchanged (backward
* compatible: every existing caller passes no branch).
* - `branch` equal to the flat slot's **on-disk** recorded branch → the
* flat handle. The disk meta is read before any cached state is trusted
* (#2364 review F1): the flat slot follows the checked-out working tree
* (#2354), so a plain analyze after a branch switch restamps the meta
* without any repo-resolution miss that would refresh a long-lived
* server's cached handle — the cached label can otherwise serve another
* branch's content under the old name (the pool staleness reinitView on GitHub (pinned to aac7515d2a)
Solutions
- Read the 'Available: ...' list in the error (or call list_repos) and pass one of those exact names.
- For duplicate names, copy the label's parenthesized absolute path and pass that path as repo.
- If the target repo genuinely is not indexed, run `gitnexus analyze` inside it, then retry.
- If the repo moved on disk, re-run analyze from its new location so the registry records the current path.
Example fix
# before: stale name after rename
{"tool": "impact", "args": {"target": "oldName:login", "repo": "old-project"}}
# after: use a name from the Available list (or its absolute path)
{"tool": "impact", "args": {"target": "login", "repo": "renamed-project"}}
# duplicate names → disambiguate by path:
{"tool": "impact", "args": {"target": "login", "repo": "/srv/checkouts/a/renamed-project"}} Defensive patterns
Strategy: validation
Validate before calling
// Validate the repo param against the live registry before tool calls
const { repositories } = await client.callTool({ name: 'list_repos', arguments: {} });
const valid = new Set(repositories.flatMap((r: any) => [r.name, r.repo_path ?? r.path]));
function assertKnownRepo(repoParam: string): void {
if (!valid.has(repoParam) && !valid.has(repoParam.toLowerCase())) {
throw new Error(`repo "${repoParam}" not in registry. Known: ${[...valid].join(', ')}`);
}
} Type guard
const isKnownRepoHandle = (name: string, repos: Array<{ name: string; repoPath?: string }>): boolean =>
repos.some((r) => r.name.toLowerCase() === name.toLowerCase() || r.repoPath === name); Try / catch
try {
return await client.callTool({ name: 'context', arguments: { ...args, repo } });
} catch (err) {
if (err instanceof Error && err.message.startsWith('Repository "')) {
// parse the Available list and re-ask the user / re-resolve the name
const available = err.message.split('Available: ')[1]?.split(', ') ?? [];
throw new UserChoiceError(`Unknown repo "${repo}". Pick one of: ${available.join(', ')}`);
}
throw err;
} Prevention
- Fetch list_repos once at client startup and validate every repo param against it.
- Re-run analyze after renaming or moving a repository so the registry stays current.
- Prefer absolute paths as stable repo identifiers across machines.
- For duplicate names, always use the parenthesized path from the error's Available list.
When it happens
Trigger: Passing repo: "myrepo" when the indexed name differs (rename, typo, wrong casing beyond the case-insensitive match), passing an id that no longer exists, or targeting a repo indexed under a different absolute path after it was moved/cloned elsewhere.
Common situations: Hard-coded repo names in MCP client configs drifting after project renames; moving or re-cloning a repo to a new directory so the registered handle no longer matches; multiple machines with different indexed sets; stale docs referencing old repo names.
Related errors
- Multiple repositories indexed. Specify which one with the "r
- Multiple registered repos match "${target}": ${listing} Pass
- No indexed repositories. Run: gitnexus analyze
- Multiple registered repos match "${target}": ${listing} Pass
- No registered repo matches "${target}".${hint}
AI-assisted analysis of abhigyanpatwari/GitNexus@aac7515d2a (2026-08-20).
Data as JSON: /api/errors/a97caabff799cfed.
Report an issue: GitHub.