slopus/happy · error

ACP session not started

Error message

ACP session not started

What it means

runGemini communicates with the Gemini CLI via ACP (Agent Client Protocol). A session ID is only assigned after the ACP handshake completes. When the UI update path runs and acpSessionId is still unset, the code throws rather than send a prompt against a non-existent session. This guards against sending user input before the backend is ready.

Source

Thrown at packages/happy-cli/src/gemini/runGemini.ts:1050

          
          // Start session if not started
          if (!acpSessionId) {
            logger.debug('[gemini] Starting ACP session...');
            // Update permission handler with current permission mode before starting session
            updatePermissionMode(message.mode.permissionMode);
            const { sessionId } = await geminiBackend.startSession();
            acpSessionId = sessionId;
            logger.debug(`[gemini] ACP session started: ${acpSessionId}`);
            wasSessionCreated = true;
            currentModeHash = message.hash;
            
            // Model info is already shown in status bar via updateDisplayedModel
            logger.debug(`[gemini] Displaying model in UI: ${displayedModel || 'gemini-2.5-pro'}, displayedModel: ${displayedModel}`);
          }
        }
        
        if (!acpSessionId) {
          throw new Error('ACP session not started');
        }
         
        // Reset accumulator when sending a new prompt (not when tool calls start)
        // Reset accumulated response for new prompt
        // This ensures a new assistant message will be created (not updating previous one)
        accumulatedResponse = '';
        isResponseInProgress = false;
        hadToolCallInTurn = false;
        taskStartedSent = false; // Reset so new turn can send task_started
        
        // Track if this prompt contains change_title instruction
        // If so, don't send task_complete until change_title is completed
        pendingChangeTitle = message.message.includes('change_title') || 
                             message.message.includes('happy__change_title');
        changeTitleCompleted = false;
        
        if (!geminiBackend || !acpSessionId) {
          throw new Error('Gemini backend or session not initialized');

View on GitHub (pinned to b824cd0a46)

Solutions

  1. Wait for the session-ready signal/UI indicator before typing or sending a prompt
  2. Check the gemini CLI is installed, on PATH, and starts correctly (run `gemini --version`)
  3. Restart the session; if it reproduces, enable debug logging to see why the ACP handshake never returned a session ID
Defensive patterns

Strategy: validation

Validate before calling

if (!acpSessionId) {
  logger.warn('[gemini] ACP session not ready; skipping prompt');
  return;
}

Type guard

const hasAcpSession = (id: string | null | undefined): id is string => typeof id === 'string' && id.length > 0;

Try / catch

try {
  await sendPromptToAcp(prompt);
} catch (err) {
  if (err instanceof Error && err.message === 'ACP session not started') {
    await waitForSessionReady();
    await sendPromptToAcp(prompt);
  } else throw err;
}

Prevention

When it happens

Trigger: Inside runGemini, the prompt/display flow is reached while the acpSessionId variable is still null/undefined — i.e. the ACP initialize/newSession handshake has not produced a session ID yet when a prompt arrives.

Common situations: User submits a prompt before the Gemini ACP process finished initializing; the gemini binary fails or is slow to start; an earlier session initialization error was swallowed so acpSessionId never gets set.

Related errors


AI-assisted analysis of slopus/happy@b824cd0a46 (2026-08-31). Data as JSON: /api/errors/5bac0c9fa549d193. Report an issue: GitHub.