google-gemini/gemini-cli

bug: TUI hangs indefinitely on "Initializing..." — IdeClient.getInstance() blocks BuiltinCommandLoader in bare terminal

Open

#21 477 ouverte le 6 mars 2026

Voir sur GitHub
 (11 commentaires) (0 réactions) (1 assigné)TypeScript (13 657 forks)batch import
area/coreeffort/largehelp wantedkind/bugpriority/p1status/bot-triagedstatus/need-retestingstatus/possible-duplicatetype/bug

Métriques du dépôt

Stars
 (103 992 stars)
Métriques de merge PR
 (Merge moyen 4j 2h) (55 PRs mergées en 30 j)

Description

Description

Gemini CLI v0.32.1 interactive TUI hangs forever on the "Initializing..." spinner when launched from a bare Linux terminal (not inside any IDE). Headless mode (gemini -p "hello") works perfectly.

Root Cause (Diagnosed)

The hang originates in BuiltinCommandLoader.loadCommands() which awaits ideCommand(). This calls IdeClient.getInstance()getIdeProcessInfo()getProcessInfo(pid) which runs ps -o ppid=,command= -p <pid> in a loop, traversing up the process tree looking for a parent IDE.

On certain Linux systems running from a bare terminal, this process traversal never completes — the execAsync('ps ...') call hangs on a specific PID in the ancestor chain.

Because BuiltinCommandLoader never resolves, Promise.allSettled() in CommandService.create() never settles, slashCommands is never set, and the TUI condition (!uiState.slashCommands || !uiState.isConfigInitialized) keeps rendering ConfigInitDisplay ("Initializing...") forever.

Evidence from instrumentation

Added fs.appendFileSync logging to each loader in CommandService.create():

[CMD] loader[0] McpPromptLoader DONE
[CMD] loader[2] FileCommandLoader DONE
# loader[1] BuiltinCommandLoader — NEVER completes

[BUILTIN] isNightly DONE: false
[BUILTIN] ideCommand START
# ideCommand — NEVER completes

config.initialize() completes in ~120ms. The issue is exclusively in the slash command loading phase.

Suggested Fix

Add a timeout to ideCommand() in BuiltinCommandLoader.loadCommands(), or make getIdeProcessInfo() non-blocking with an AbortSignal / timeout. When running from a bare terminal (no IDE detected within N seconds), it should fall back gracefully instead of blocking startup indefinitely.

Example:

// Instead of:
await ideCommand(),

// Use:
await Promise.race([
  ideCommand(),
  new Promise(resolve => setTimeout(() => resolve(noIdeFallbackCommand), 5000))
]),

Workaround

Replace await ideCommand(), in BuiltinCommandLoader.js with a static no-IDE object:

GEMINI_PATH=$(dirname $(readlink -f $(which gemini)))/../lib/node_modules/@google/gemini-cli
sed -i "s|await ideCommand(),|{ name: 'ide', description: 'Manage IDE integration (disabled)', kind: 'built-in', autoExecute: false, action: () => ({ type: 'message', messageType: 'info', content: 'IDE integration is not available.' }) },|" \
  "$GEMINI_PATH/dist/src/services/BuiltinCommandLoader.js"

Environment

  • OS: Ubuntu 24.04+ (Linux 6.17.0-14-generic, x86_64)
  • Gemini CLI: v0.32.1
  • Node.js: v24.14.0
  • Terminal: GNOME Terminal / bare terminal (NOT inside VS Code, Cursor, or any IDE)
  • Shell: bash

Steps to Reproduce

  1. Install Gemini CLI on Ubuntu Linux: npm install -g @google/gemini-cli
  2. Authenticate: gemini -p "hello" (works fine in headless)
  3. Launch interactive TUI from a bare terminal: gemini
  4. Observe: TUI shows logo, briefly flashes "Waiting for auth...", then stays on "Initializing..." forever
  5. Confirm headless works: gemini -p "hello" responds normally

Related Issues

  • #13986 (TUI stuck at Initializing — attributed to MCP, but may also be this bug)
  • #20433 (Initializing hang due to ripgrep — different root cause, same symptom)

Guide contributeur