{"record":{"id":"ff3d255d386df18b","repo":"slopus/happy","slug":"acp-session-is-not-started","errorCode":null,"errorMessage":"ACP session is not started","messagePattern":"ACP session is not started","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/happy-cli/src/agent/acp/runAcp.ts","lineNumber":910,"sourceCode":"        logAcp('muted', `Outgoing models from ${opts.agentName}: not reported yet`);\n      }\n    }\n\n    while (!shouldExit) {\n      const waitSignal = abortController.signal;\n      const batch = await messageQueue.waitForMessagesAndGetAsString(waitSignal);\n      if (!batch) {\n        if (shouldExit) {\n          break;\n        }\n        if (waitSignal.aborted) {\n          continue;\n        }\n        break;\n      }\n\n      if (!acpSessionId) {\n        throw new Error('ACP session is not started');\n      }\n\n      logAcp('incoming', `Incoming prompt: ${formatUnknownForConsole(batch.message, ACP_EVENT_PREVIEW_CHARS)}`);\n      sendEnvelopes(sessionManager.startTurn());\n      const turnEnded = waitForTurnEnd();\n      try {\n        if (typeof batch.mode.permissionMode === 'string' && batch.mode.permissionMode.length > 0) {\n          await switchPermissionModeIfRequested(batch.mode.permissionMode);\n        }\n        if (typeof batch.mode.model === 'string' && batch.mode.model.length > 0) {\n          await switchModelIfRequested(batch.mode.model);\n        }\n        await backend.sendPrompt(acpSessionId, batch.message);\n        await turnEnded;\n        sendEnvelopes(sessionManager.endTurn('completed'));\n        session.sendSessionEvent({ type: 'ready' });\n        if (verbose) {\n          logAcp('muted', `Outgoing prompt completion from ${opts.agentName}`);","sourceCodeStart":892,"sourceCodeEnd":928,"githubUrl":"https://github.com/slopus/happy/blob/b824cd0a4681d41af631a8e422a813873e4455b0/packages/happy-cli/src/agent/acp/runAcp.ts#L892-L928","documentation":"runAcp's message loop batches user prompts and only forwards them once the ACP session handshake produced an acpSessionId. If a prompt arrives and acpSessionId is still unset (session start never completed or failed), the loop throws this error before sending the turn.","triggerScenarios":"User submits a prompt while the agent's initialize/newSession handshake is still in flight; session start failed earlier (agent error/crash) but the UI still accepted input; first prompt raced ahead of session establishment.","commonSituations":"Typing immediately after launching `happy acp <agent>` on a slow-to-start agent; agent binary that hangs during handshake; retrying a prompt after a failed session without restarting.","solutions":["Wait for the 'session started'/ready indicator before sending the first prompt.","Check earlier logAcp/status output for a session-start failure and restart the backend.","If the agent hangs at startup, verify the command runs and completes the ACP handshake standalone.","Increase startup timeouts if the agent is slow but healthy."],"exampleFix":"// before\nawait runAcp({ agentName: 'claude-code' }); // prompt sent instantly\n// after\nawait ready;                 // wait for session-ready promise\nawait runAcp({ agentName: 'claude-code' });","handlingStrategy":"validation","validationCode":"await sessionReadyPromise; // resolves when acpSessionId is set\n// only then allow prompts:\nsubmitPromptButton.enabled = true;","typeGuard":"function sessionStarted(state: { acpSessionId?: string | null }): state is { acpSessionId: string } {\n  return typeof state.acpSessionId === 'string' && state.acpSessionId.length > 0;\n}","tryCatchPattern":"try {\n  await waitForTurnEnd();\n} catch (err) {\n  if (err instanceof Error && err.message === 'ACP session is not started') {\n    console.error('Agent session never started; check agent startup logs and restart.');\n  } else throw err;\n}","preventionTips":["Disable prompt input until the session-ready event fires.","Investigate session-start failures instead of letting prompts queue behind them.","Test slow-starting agents to confirm the UI waits for the handshake.","Add a startup timeout with a clear error if the agent never completes the handshake."],"tags":["session","race-condition","acp","initialization"],"backgroundTag":"session-not-initialized","analyzedSha":"b824cd0a4681d41af631a8e422a813873e4455b0","analyzedAt":"2026-08-31T23:12:36.205Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}