google-gemini/gemini-cli · error

Invalid or unavailable mode: ${modeId}

Error message

Invalid or unavailable mode: ${modeId}

What it means

setMode() looks up the requested mode ID in the list returned by buildAvailableModes(). The always-available modes are 'default', 'auto_edit', and 'yolo' (mapped from ApprovalMode enum values). The 'plan' mode is only included when config.isPlanEnabled() returns true. An unrecognized or currently-unavailable mode ID triggers this error.

Source

Thrown at packages/cli/src/acp/acpSession.ts:213

    this.disposeController.abort();
  }

  async cancelPendingPrompt(): Promise<void> {
    if (!this.pendingPrompt) {
      throw new Error('Not currently generating');
    }

    this.pendingPrompt.abort();
    this.pendingPrompt = null;
  }

  setMode(modeId: acp.SessionModeId): acp.SetSessionModeResponse {
    const availableModes = buildAvailableModes(
      this.context.config.isPlanEnabled(),
    );
    const mode = availableModes.find((m) => m.id === modeId);
    if (!mode) {
      throw new Error(`Invalid or unavailable mode: ${modeId}`);
    }
    // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
    this.context.config.setApprovalMode(mode.id as ApprovalMode);
    return {};
  }

  private getAvailableCommands() {
    return this.commandHandler.getAvailableCommands();
  }

  async sendAvailableCommands(): Promise<void> {
    const availableCommands = this.getAvailableCommands().map((command) => ({
      name: command.name,
      description: command.description,
    }));

    await this.sendUpdate({
      sessionUpdate: 'available_commands_update',

View on GitHub (pinned to 5024443c72)

Solutions

  1. Use the availableModes list from the session initialize response and only send IDs found there.
  2. If requesting plan mode, ensure plan is enabled in the server-side configuration (config.isPlanEnabled()).
  3. Check isPlanEnabled() on the config before attempting to set plan mode.

Example fix

// before
session.setMode('plan' as acp.SessionModeId); // throws if plan disabled

// after
const modes = buildAvailableModes(config.isPlanEnabled());
if (modes.some((m) => m.id === targetModeId)) {
  session.setMode(targetModeId);
} else {
  // handle unavailable mode
}
Defensive patterns

Strategy: validation

Validate before calling

import { buildAvailableModes } from './acpUtils.js';

function isModeAvailable(modeId: string, isPlanEnabled: boolean): boolean {
  return buildAvailableModes(isPlanEnabled).some((m) => m.id === modeId);
}

// Before calling setMode:
if (!isModeAvailable(targetModeId, config.isPlanEnabled())) {
  throw new Error(`Mode ${targetModeId} is not available in this configuration.`);
}
session.setMode(targetModeId as acp.SessionModeId);

Prevention

When it happens

Trigger: Passing a modeId not in the available list — e.g., 'plan' when plan mode is disabled in config, or any unknown string. The available modes are advertised in the session initialize response via buildAvailableModes().

Common situations: Client sends 'plan' mode without plan being enabled in the server config; version mismatch between client and server mode lists; client using a mode ID from a newer or older protocol version.

Related errors


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