{"record":{"id":"ae87e3d19d7b384a","repo":"tinyhumansai/openhuman","slug":"session-store-mutex-poisoned","errorCode":null,"errorMessage":"session store mutex poisoned","messagePattern":"session store mutex poisoned","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/openhuman/inference/provider/claude_code/session_store.rs","lineNumber":44,"sourceCode":"}\n\nimpl SessionStore {\n    /// Open (or initialize) the session store at `workspace/claude-code-sessions.json`.\n    pub fn open(workspace_dir: &Path) -> Self {\n        let path = workspace_dir.join(\"claude-code-sessions.json\");\n        let inner = std::fs::read_to_string(&path)\n            .ok()\n            .and_then(|s| serde_json::from_str::<StoreFile>(&s).ok())\n            .unwrap_or_default();\n        Self {\n            path,\n            inner: Mutex::new(inner),\n        }\n    }\n\n    /// Lookup an existing CC session UUID for `thread_id`.\n    pub fn get(&self, thread_id: &str) -> Option<String> {\n        let guard = self.inner.lock().expect(\"session store mutex poisoned\");\n        guard.sessions.get(thread_id).cloned()\n    }\n\n    /// Persist a thread → UUID mapping.\n    pub fn set(&self, thread_id: &str, uuid: &str) -> std::io::Result<()> {\n        let mut guard = self.inner.lock().expect(\"session store mutex poisoned\");\n        guard\n            .sessions\n            .insert(thread_id.to_string(), uuid.to_string());\n        let serialized = serde_json::to_string_pretty(&*guard).map_err(std::io::Error::other)?;\n        if let Some(parent) = self.path.parent() {\n            std::fs::create_dir_all(parent)?;\n        }\n        std::fs::write(&self.path, serialized)\n    }\n}\n\n/// Random RFC-4122 v4 UUID, formatted lower-case with hyphens.","sourceCodeStart":26,"sourceCodeEnd":62,"githubUrl":"https://github.com/tinyhumansai/openhuman/blob/749120085864ce16e0f273c7b86fac7740b39c5b/src/openhuman/inference/provider/claude_code/session_store.rs#L26-L62","documentation":"Mutex poisoning on the claude-code session store's inner mutex (workspace/claude-code-sessions.json mapping thread_id -> CC session UUID): a panic during get/set while holding the lock poisons it, and a subsequent lock() expect fails. Session persistence for the Claude Code provider becomes unusable until restart; the original panic is the root cause.","triggerScenarios":"Thrown at src/openhuman/inference/provider/claude_code/session_store.rs:44 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Find the earlier panic in the logs that poisoned the store lock","Use lock().unwrap_or_else(|e| e.into_inner()) — the JSON map is still structurally valid after a panic between operations","Keep lock scope minimal around the read-modify-write in set()"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"749120085864ce16e0f273c7b86fac7740b39c5b","analyzedAt":"2026-08-17T21:21:45.363Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}