google-gemini/gemini-cli · error · Error

Command '${command}' timed out after ${COMMAND_TIMEOUT_MS /

Error message

Command '${command}' timed out after ${COMMAND_TIMEOUT_MS / 1000} seconds

What it means

Thrown by resolveAuthValue when the spawned shell command exceeded COMMAND_TIMEOUT_MS (60000ms / 60s). The AbortSignal.timeout aborts spawnAsync; the catch detects error.name === 'AbortError' and re-wraps it with this message.

Source

Thrown at packages/core/src/agents/auth-provider/value-resolver.ts:74

    const shellConfig = getShellConfiguration();
    try {
      const { stdout } = await spawnAsync(
        shellConfig.executable,
        [...shellConfig.argsPrefix, command],
        {
          signal: AbortSignal.timeout(COMMAND_TIMEOUT_MS),
          windowsHide: true,
        },
      );

      const trimmed = stdout.trim();
      if (!trimmed) {
        throw new Error(`Command '${command}' returned empty output`);
      }
      return trimmed;
    } catch (error) {
      if (error instanceof Error && error.name === 'AbortError') {
        throw new Error(
          `Command '${command}' timed out after ${COMMAND_TIMEOUT_MS / 1000} seconds`,
        );
      }
      throw error;
    }
  }

  // Literal value - return as-is
  return value;
}

/**
 * Check if a value needs resolution (is an env var or command reference).
 */
export function needsResolution(value: string): boolean {
  return value.startsWith('$') || value.startsWith('!');
}

View on GitHub (pinned to 5024443c72)

Solutions

  1. Run the command standalone and time it; if it is genuinely slow, cache its output into an env var instead.
  2. Ensure the command is non-interactive: pass flags that suppress prompts (--no-input, batch mode) or pre-seed credentials.
  3. Check for a stale lock or hung daemon the command depends on and restart it.
  4. If 60s is insufficient for a legitimate slow command, pre-resolve the value into an environment variable and reference it with $VAR instead.

Example fix

# before: interactive prompt hangs
accessToken: '!aws sts get-session-token ...'  # prompts for MFA, blocks

# after: non-interactive, cached
export TOKEN=$(aws sts get-session-token --token-code 123456 --query Credentials.SessionToken --output text)
accessToken: '$TOKEN'
Defensive patterns

Strategy: retry

Validate before calling

// Pre-flight timing check.
import { spawnSync } from 'node:child_process';
function isCmdFastEnough(cmd, limitMs = 55_000) {
  const t0 = Date.now();
  spawnSync(cmd, { shell: true, timeout: limitMs });
  return Date.now() - t0 < limitMs;
}

Try / catch

try {
  const val = await resolveAuthValue('!slow-cmd');
} catch (e) {
  if (e instanceof Error && /timed out/.test(e.message)) {
    // switch to a cached env var, or make the command non-interactive
  }
  throw e;
}

Prevention

When it happens

Trigger: resolveAuthValue('!cmd') where cmd takes longer than 60 seconds. spawnAsync receives AbortSignal.timeout(60_000); on abort the AbortError is caught and converted to a domain-specific timeout error.

Common situations: Command prompts for input interactively (password / MFA) and blocks forever waiting on a TTY that is not present; command makes a slow network call (e.g. a cloud metadata or STS call behind a slow link); command is waiting on a lock; command shells out to a daemon that is hung.

Understand the failure class

Related errors


AI-assisted analysis of google-gemini/gemini-cli@5024443c72 (2026-08-12). Data as JSON: /api/errors/46f5084fe9f2c501. Report an issue: GitHub.