google-gemini/gemini-cli · error · ConfirmationRequiredError

Shell command confirmation required

Error message

Shell command confirmation required

What it means

Thrown as a ConfirmationRequiredError when one or more resolved shell commands received PolicyDecision.ASK_USER. The error carries commandsToConfirm (the list of commands needing approval). In contexts without an interactive confirmation flow this aborts; in interactive mode it drives the confirmation UI.

Source

Thrown at packages/cli/src/services/prompt-processors/shellProcessor.ts:146

        {
          name: 'run_shell_command',
          args: { command },
        },
        undefined,
      );

      if (decision === PolicyDecision.DENY) {
        throw new Error(
          `${this.commandName} cannot be run. Blocked command: "${command}". Reason: Blocked by policy.`,
        );
      } else if (decision === PolicyDecision.ASK_USER) {
        commandsToConfirm.add(command);
      }
    }

    // Handle confirmation requirements.
    if (commandsToConfirm.size > 0) {
      throw new ConfirmationRequiredError(
        'Shell command confirmation required',
        Array.from(commandsToConfirm),
      );
    }

    let processedPrompt = '';
    let lastIndex = 0;

    for (const injection of resolvedInjections) {
      // Append the text segment BEFORE the injection, substituting {{args}} with RAW input.
      const segment = prompt.substring(lastIndex, injection.startIndex);
      processedPrompt += segment.replaceAll(
        SHORTHAND_ARGS_PLACEHOLDER,
        userArgsRaw,
      );

      // Execute the resolved command (which already has ESCAPED input).
      if (injection.resolvedCommand) {

View on GitHub (pinned to 5024443c72)

Solutions

  1. Run in interactive mode and approve the command when prompted (approval can add it to the allowlist).
  2. Pre-populate the session shell allowlist or an allow policy rule for the command so it no longer triggers ASK_USER.
  3. Catch ConfirmationRequiredError in programmatic callers and present the commandsToConfirm list to your own approval flow, then retry with an updated allowlist.

Example fix

// programmatic handling
try {
  await shellProcessor.process(prompt, ctx);
} catch (e) {
  if (e instanceof ConfirmationRequiredError) {
    showApprovals(e.commandsToConfirm);
  } else throw e;
}
Defensive patterns

Strategy: try-catch

Validate before calling

async function needsConfirmation(commands: string[], config: Config): Promise<string[]> {
  const out: string[] = [];
  for (const c of commands) {
    const { decision } = await config.getPolicyEngine().check({ name: 'run_shell_command', args: { command: c } }, undefined);
    if (decision === PolicyDecision.ASK_USER) out.push(c);
  }
  return out;
}

Type guard

import { ConfirmationRequiredError } from './shellProcessor.js';
function isConfirmationRequired(e: unknown): e is ConfirmationRequiredError {
  return e instanceof ConfirmationRequiredError;
}

Try / catch

try {
  await shellProcessor.process(prompt, ctx);
} catch (e) {
  if (e instanceof ConfirmationRequiredError) {
    // e.commandsToConfirm lists commands needing approval; run your own approval flow,
    // add approved ones to session.sessionShellAllowlist, then retry.
  } else throw e;
}

Prevention

When it happens

Trigger: The policy engine returns ASK_USER for at least one '!{...}' command that is not on the session shell allowlist, so commandsToConfirm is non-empty and ConfirmationRequiredError is thrown.

Common situations: A shell injection command is neither allowed nor denied, so policy asks the user; running in non-interactive mode where there is no way to ask; first use of a command that has not yet been approved/allowlisted.

Related errors


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