abhigyanpatwari/GitNexus · error
Multiple repositories indexed. Specify which one with the "r
Error message
Multiple repositories indexed. Specify which one with the "repo" parameter. Available: ${labels.join(', ')} What it means
Repo resolution reached its fallback with no repo parameter supplied while the registry holds multiple repos: there is no single default to choose, so LocalBackend throws and lists all handles (paths added to duplicate names per #829). The caller must disambiguate via the repo parameter — or rely on cwd-based auto-selection, which already had its chance via pickRepoHandleForCwd.
Source
Thrown at gitnexus/src/mcp/local/local-backend.ts:1744
}
// 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 reinit
* hot-swaps content without updating `handle.branch`).
* - `branch` matching an indexed pinned branch → a handle whoseView on GitHub (pinned to aac7515d2a)
Solutions
- Add the repo parameter with one of the listed names (or an absolute path for duplicate names).
- Or run the client from inside the target repository's directory so cwd-based selection can auto-pick it.
- Call list_repos first to enumerate valid handles and their exact labels.
- If you only ever work with one repo, consider removing the others from the registry to restore implicit defaulting.
Example fix
# before: ambiguous call, two repos indexed
{"tool": "context", "args": {"name": "parseRepo"}}
# → Multiple repositories indexed. Specify which one with the "repo" parameter. ...
# after: explicit repo (name, or absolute path when names collide)
{"tool": "context", "args": {"name": "parseRepo", "repo": "gitnexus"}} Defensive patterns
Strategy: validation
Validate before calling
// Make the repo param mandatory in your own client wrapper
async function withRepo<T>(tool: string, args: Record<string, unknown>, cwd: string): Promise<T> {
if (args.repo) return client.callTool({ name: tool, arguments: args }) as Promise<T>;
const { repositories } = await client.callTool({ name: 'list_repos', arguments: {} });
if (repositories.length === 1) return client.callTool({ name: tool, arguments: { ...args, repo: repositories[0].name } }) as Promise<T>;
const inferred = repositories.find((r: any) => cwd.startsWith(r.repo_path ?? r.path));
if (!inferred) throw new Error(`Multiple repos indexed (${repositories.length}) — pass repo or run from inside one`);
return client.callTool({ name: tool, arguments: { ...args, repo: inferred.name } }) as Promise<T>;
} Try / catch
try {
return await client.callTool({ name: 'impact', arguments: args });
} catch (err) {
if (err instanceof Error && err.message.startsWith('Multiple repositories indexed')) {
const available = err.message.split('Available: ')[1];
throw new UserChoiceError(`Pick a repo: ${available}`); // surface the choice, never guess
}
throw err;
} Prevention
- Always populate the repo field in multi-repo setups; never rely on implicit defaulting.
- Run the MCP client from inside the target checkout so cwd-based selection can work.
- Cache the list_repos result and prompt/select when multiple entries exist.
- Prune stale entries from the registry when a project is archived.
When it happens
Trigger: Indexing two or more repos (e.g. a CLI package and its web app) and then calling impact/query/context without a repo field from a working directory that is not inside any indexed repo.
Common situations: MCP client configs written when only one repo was indexed, then a second repo gets added; agents running from a neutral directory (home, /tmp) while multiple projects are indexed; shared team MCP servers serving several repos.
Related errors
- Multiple registered repos match "${target}": ${listing} Pass
- Repository "${repoParam}" not found. Available: ${labels.joi
- No indexed repositories. Run: gitnexus analyze
- Multiple registered repos match "${target}": ${listing} Pass
- Missing Content-Length header from MCP client
AI-assisted analysis of abhigyanpatwari/GitNexus@aac7515d2a (2026-08-20).
Data as JSON: /api/errors/da3f88508aebb2fd.
Report an issue: GitHub.