abhigyanpatwari/GitNexus · error
Group routing is not available in GitNexus MCP read-only mod
Error message
Group routing is not available in GitNexus MCP read-only mode.
What it means
Thrown by assertMcpReadOnlyToolCall when read-only mode is active and a tool call passes a repo argument that starts with '@' (the cross-repo group routing syntax, e.g. repo: '@my-group'). Read-only mode deliberately disables group routing, so any @-prefixed repo is rejected at dispatch before the backend sees it.
Source
Thrown at gitnexus/src/mcp/read-only-policy.ts:40
export function resolveMcpReadOnlyMode(env: NodeJS.ProcessEnv = process.env): boolean {
const value = env.GITNEXUS_MCP_READ_ONLY?.trim();
if (value === undefined || value === '' || value === '0') return false;
if (value === '1') return true;
throw new Error('GITNEXUS_MCP_READ_ONLY must be 0 or 1.');
}
export function assertMcpReadOnlyToolCall(
toolName: string,
args: Record<string, unknown> | undefined,
readOnly: boolean,
): void {
if (!readOnly) return;
if (!MCP_READ_ONLY_TOOLS.has(toolName) && !MCP_READ_ONLY_ALIASES.has(toolName)) {
throw new Error(`Tool "${toolName}" is not available in GitNexus MCP read-only mode.`);
}
if (typeof args?.repo === 'string' && args.repo.trim().startsWith('@')) {
throw new Error('Group routing is not available in GitNexus MCP read-only mode.');
}
// crossDepth/subgroup only do anything on the @group path rejected above,
// but rejecting them here keeps the advertised schema and the dispatch
// contract in agreement.
for (const groupOnlyArg of ['crossDepth', 'subgroup']) {
if (args?.[groupOnlyArg] !== undefined) {
throw new Error(
`Parameter "${groupOnlyArg}" is not available in GitNexus MCP read-only mode.`,
);
}
}
}
export function readOnlyResourceTemplateAllowed(uriTemplate: string, readOnly: boolean): boolean {
return !readOnly || !/^gitnexus:\/\/group\//iu.test(uriTemplate);
}
export function assertMcpReadOnlyResource(uri: string, readOnly: boolean): void {View on GitHub (pinned to aac7515d2a)
Solutions
- Pass a concrete repository name or path instead of the @group specifier, e.g. repo: 'GitNexus' or repo: '/srv/repos/frontend'.
- Issue one call per repository instead of one group-routed call.
- If group routing is required, disable read-only mode (unset GITNEXUS_MCP_READ_ONLY or set it to 0) after reviewing the security trade-off.
Example fix
// before
await client.callTool({ name: 'query', arguments: { search_query: 'auth', repo: '@my-group' } });
// after
for (const repo of ['frontend', 'backend']) {
await client.callTool({ name: 'query', arguments: { search_query: 'auth', repo } });
} Defensive patterns
Strategy: validation
Validate before calling
function assertRepoArg(repo: unknown, readOnly: boolean) {
if (readOnly && typeof repo === 'string' && repo.trim().startsWith('@')) {
throw new Error('Group routing (@repo) is disabled on this read-only endpoint; pass a concrete repo.');
}
} Type guard
const isConcreteRepo = (repo: unknown): repo is string =>
typeof repo === 'string' && repo.trim().length > 0 && !repo.trim().startsWith('@'); Try / catch
try {
await client.callTool({ name: 'query', arguments: { search_query: q, repo } });
} catch (e) {
if (e instanceof Error && e.message.includes('Group routing is not available')) {
// fall back to per-repo calls over a known list
for (const r of repoList) await runQuery(q, r);
} else throw e;
} Prevention
- Derive the repo argument from deployment config, never hard-code '@group' in shared templates.
- Detect read-only mode once at startup (from server info/env) and select the argument strategy then.
- Prefer explicit per-repo iteration; it works in both modes.
When it happens
Trigger: With GITNEXUS_MCP_READ_ONLY=1, calling any allowlisted tool with arguments like { repo: '@frontend' } or { repo: ' @backend' } (leading whitespace is trimmed, so it still triggers).
Common situations: A client reuses group-routing arguments from a read-write deployment ('repo: "@org"') against a hardened read-only endpoint. Agents copy the @group example from cross-repo docs without noticing the deployment difference.
Related errors
- Tool "${toolName}" is not available in GitNexus MCP read-onl
- Parameter "${groupOnlyArg}" is not available in GitNexus MCP
- Group resources are not available in GitNexus MCP read-only
- Group routing is unavailable when an MCP repository allowlis
- GITNEXUS_MCP_READ_ONLY must be 0 or 1.
AI-assisted analysis of abhigyanpatwari/GitNexus@aac7515d2a (2026-08-20).
Data as JSON: /api/errors/0e164e2b9eb1346e.
Report an issue: GitHub.