abhigyanpatwari/GitNexus · error

GITNEXUS_MCP_READ_ONLY must be 0 or 1.

Error message

GITNEXUS_MCP_READ_ONLY must be 0 or 1.

What it means

Thrown by resolveMcpReadOnlyMode when the GITNEXUS_MCP_READ_ONLY environment variable is set to anything other than the exact recognized values. After trimming, only undefined (unset), '' (empty), '0' (read-write) and '1' (read-only) are accepted. The check is strict because this variable turns the MCP server into a hardened read-only surface, so loose truthiness parsing ('true', 'yes', 'on') is intentionally rejected.

Source

Thrown at gitnexus/src/mcp/read-only-policy.ts:27

  'detect_changes',
  'check',
  'impact',
  'explain',
  'pdg_query',
  'route_map',
  'tool_map',
  'shape_check',
  'api_impact',
  'trace',
]);

const MCP_READ_ONLY_ALIASES = new Set(['search', 'explore', 'overview']);

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']) {

View on GitHub (pinned to aac7515d2a)

Solutions

  1. Set the variable to exactly 1 (enable read-only) or 0 (disable), e.g. GITNEXUS_MCP_READ_ONLY=1 npx gitnexus mcp.
  2. Unset the variable entirely if you want read-write mode — undefined and empty both mean off.
  3. Search the environment and .env files for the variable and correct every occurrence; do not use true/false/yes/no spellings.

Example fix

# before
export GITNEXUS_MCP_READ_ONLY=true

# after
export GITNEXUS_MCP_READ_ONLY=1
Defensive patterns

Strategy: validation

Validate before calling

const raw = process.env.GITNEXUS_MCP_READ_ONLY;
const readOnly = raw === undefined || raw.trim() === '' || raw.trim() === '0' ? false : raw.trim() === '1';
if (readOnly === undefined && !(raw!.trim() === '1')) {
  throw new Error(`GITNEXUS_MCP_READ_ONLY has invalid value: ${JSON.stringify(raw)}`);
}

Type guard

const isValidReadOnlyEnv = (v: string | undefined): boolean =>
  v === undefined || ['', '0', '1'].includes(v.trim());

Try / catch

try {
  spawnGitnexusMcp();
} catch (e) {
  if (e instanceof Error && e.message.includes('GITNEXUS_MCP_READ_ONLY')) {
    // config error: fix the env value and restart; retrying unchanged cannot help
  }
  throw e;
}

Prevention

When it happens

Trigger: Starting the GitNexus MCP server with GITNEXUS_MCP_READ_ONLY set to 'true', 'yes', 'on', '2', 'TRUE', 'read', or any other string; the error surfaces as soon as the policy is resolved at startup or on first tool/resource dispatch.

Common situations: Operators habitually write GITNEXUS_MCP_READ_ONLY=true (shell/COMMON convention) instead of 1. A .env loader keeps a quoted or padded value. Upgrading from a version that ignored the variable to one that enforces it.

Understand the failure class

Background: "is not a valid" / "Invalid ... value" environment variable errors: how libraries validate env vars and what to do when they reject yours — this error's family across 48 libraries.

Related errors


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