{"record":{"id":"b6a73e9d38169f84","repo":"slopus/happy","slug":"agent-state-version-mismatch","errorCode":null,"errorMessage":"Agent state version mismatch","messagePattern":"Agent state version mismatch","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"packages/happy-cli/src/api/apiSession.ts","lineNumber":975,"sourceCode":"     * Update session agent state\n     * @param handler - Handler function that returns the updated agent state\n     */\n    updateAgentState(handler: (metadata: AgentState) => AgentState) {\n        logger.debugLargeJson('Updating agent state', this.agentState);\n        this.agentStateLock.inLock(async () => {\n            await backoff(async () => {\n                let updated = handler(this.agentState || {});\n                const answer = await this.socket.emitWithAck('update-state', { sid: this.sessionId, expectedVersion: this.agentStateVersion, agentState: updated ? encodeBase64(encrypt(this.encryptionKey, this.encryptionVariant, updated)) : null });\n                if (answer.result === 'success') {\n                    this.agentState = answer.agentState ? decrypt(this.encryptionKey, this.encryptionVariant, decodeBase64(answer.agentState)) : null;\n                    this.agentStateVersion = answer.version;\n                    logger.debug('Agent state updated', this.agentState);\n                } else if (answer.result === 'version-mismatch') {\n                    if (answer.version > this.agentStateVersion) {\n                        this.agentStateVersion = answer.version;\n                        this.agentState = answer.agentState ? decrypt(this.encryptionKey, this.encryptionVariant, decodeBase64(answer.agentState)) : null;\n                    }\n                    throw new Error('Agent state version mismatch');\n                } else if (answer.result === 'error') {\n                    // console.error('Agent state update error', answer);\n                    // Hard error - ignore\n                }\n            });\n        });\n    }\n\n    /**\n     * Wait for socket buffer to flush\n     */\n    async flush(): Promise<void> {\n        await Promise.race([\n            this.sendSync.invalidateAndAwait(),\n            delay(10000)\n        ]);\n        if (!this.socket.connected) {\n            return;","sourceCodeStart":957,"sourceCodeEnd":993,"githubUrl":"https://github.com/slopus/happy/blob/b824cd0a4681d41af631a8e422a813873e4455b0/packages/happy-cli/src/api/apiSession.ts#L957-L993","documentation":"Thrown in ApiSessionClient's agent-state update path when the server responds 'version-mismatch'. The client adopts the server's newer agentStateVersion and agentState (decrypted, or null if absent), then throws to trigger a retry of the state push with the fresh version. This is the same optimistic-concurrency pattern used for metadata.","triggerScenarios":"Agent state is updated concurrently from another client attached to the same session (e.g., a second CLI instance or the mobile app), so the local agentStateVersion is behind the server's.","commonSituations":"Two machines driving one session; app reconnecting while a stale update loop from the previous connection retries; rapid successive agent-state changes racing.","solutions":["Let the retry loop resend — the client already adopted the server's newer agent state","Ensure only one writer drives the session's agent state at a time","If persistent, re-pull session state from the server before pushing updates"],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  await updateAgentState(sessionId, agentState);\n} catch (e) {\n  if (e.message === 'Agent state version mismatch') {\n    // server state already merged locally; resend converges\n    await updateAgentState(sessionId, agentState);\n  } else throw e;\n}","preventionTips":["Drive agent state from a single client per session","Treat version-mismatch as a normal conflict and retry","Re-pull agent state after reconnecting a dropped session"],"tags":["version-conflict","optimistic-concurrency","agent-state","session"],"backgroundTag":"version-mismatch","analyzedSha":"b824cd0a4681d41af631a8e422a813873e4455b0","analyzedAt":"2026-08-31T23:12:36.205Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}