abhigyanpatwari/GitNexus · error

Specify an explicit repo because multiple repositories are…

Error message

Specify an explicit repo because multiple repositories are allowed.

What it means

Thrown by McpRepositoryPolicy.repoForArgs when a repository allowlist with more than one entry is configured, the call provides no explicit repo argument, and no GITNEXUS_MCP_DEFAULT_REPO is set. With multiple allowed repositories the server cannot pick one for you, so it refuses the ambiguous call instead of guessing.

Solutions

  1. Include an explicit repo in every tool call: { search_query: 'auth', repo: 'frontend' }.
  2. Set GITNEXUS_MCP_DEFAULT_REPO to one of the allowed repositories to restore repo-optional calls.
  3. If only one repo should be served, reduce GITNEXUS_MCP_ALLOWED_REPOS to that single entry — it is then auto-selected.

Example fix

# before
await client.callTool({ name: 'query', arguments: { search_query: 'auth' } });

# after
await client.callTool({ name: 'query', arguments: { search_query: 'auth', repo: 'frontend' } });
# or server env: GITNEXUS_MCP_DEFAULT_REPO=frontend
Defensive patterns

Strategy: validation

Validate before calling

// Before calling tools when an allowlist may be set:
if (allowlistCount > 1 && !defaultRepoConfigured && args.repo === undefined) {
  throw new Error('Multiple repos allowed and no default — pass an explicit repo argument.');
}

Type guard

const hasExplicitRepo = (args: Record<string, unknown> | undefined): boolean =>
  typeof args?.repo === 'string' && args.repo.trim().length > 0;

Try / catch

try {
  await client.callTool({ name: 'query', arguments });
} catch (e) {
  if (e instanceof Error && e.message.includes('Specify an explicit repo')) {
    const repo = await promptUserForRepo(); // or read gitnexus://repos and pick
    return client.callTool({ name: 'query', arguments: { ...arguments, repo } });
  }
  throw e;
}

Prevention

When it happens

Trigger: GITNEXUS_MCP_ALLOWED_REPOS='frontend,backend' (2+ entries) and no GITNEXUS_MCP_DEFAULT_REPO, then calling a tool with no repo in the arguments — e.g. { search_query: 'auth' } only. A single-entry allowlist auto-selects that repo and does not throw.

Common situations: Growing a deployment from one repo to two: the previously optional repo argument becomes mandatory overnight and every cached agent prompt starts failing. Clients that omit repo because 'the server knows its repo' break when a second repo is indexed and allowed.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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

Appendix: source

Thrown at gitnexus/src/mcp/repository-policy.ts:151

  }

  private repoForArgs(args: Record<string, unknown> | undefined): ResolvedRepository | undefined {
    const explicit = args?.repo;
    if (explicit !== undefined) {
      if (typeof explicit !== 'string') throw unavailableRepositoryError();
      if (explicit.trim().startsWith('@')) {
        if (this.restricted) {
          throw new Error('Group routing is unavailable when an MCP repository allowlist is set.');
        }
        return undefined;
      }
      return this.resolveRuntimeRepo(explicit);
    }

    if (this.defaultRepo) return this.defaultRepo;
    if (this.restricted && this.allowed.length === 1) return this.allowed[0];
    if (this.restricted && this.allowed.length > 1) {
      throw new Error('Specify an explicit repo because multiple repositories are allowed.');
    }
    return undefined;
  }

  private normalizeToolArgs(
    args: Record<string, unknown> | undefined,
  ): Record<string, unknown> | undefined {
    if (!this.configured) return args;
    if (!this.restricted && args?.repo !== undefined) return args;
    const selected = this.repoForArgs(args);
    if (!selected) return args;
    return { ...(args ?? {}), repo: selected.path };
  }

  private async listAllowedRepos(backend: LocalBackend): Promise<RepoListing[]> {
    const current = await backend.listRepos();
    if (!this.restricted) return current;
    return current

View on GitHub (pinned to ac9a4e9abd)