{"record":{"id":"cc9254b1aa064ce1","repo":"zeroclaw-labs/zeroclaw","slug":"sqlite-connection-open-timed-out-after-seconds","errorCode":null,"errorMessage":"SQLite connection open timed out after {} seconds","messagePattern":"SQLite connection open timed out after (.+?) seconds","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/zeroclaw-memory/src/sqlite.rs","lineNumber":153,"sourceCode":"    /// Open SQLite connection, optionally with a timeout (for locked/slow storage).\n    fn open_connection(\n        db_path: &Path,\n        open_timeout_secs: Option<u64>,\n    ) -> anyhow::Result<Connection> {\n        let path_buf = db_path.to_path_buf();\n\n        let conn = if let Some(secs) = open_timeout_secs {\n            let capped = secs.min(SQLITE_OPEN_TIMEOUT_CAP_SECS);\n            let (tx, rx) = mpsc::channel();\n            thread::spawn(move || {\n                let result = Connection::open(&path_buf);\n                let _ = tx.send(result);\n            });\n            match rx.recv_timeout(Duration::from_secs(capped)) {\n                Ok(Ok(c)) => c,\n                Ok(Err(e)) => return Err(e).context(\"SQLite failed to open database\"),\n                Err(mpsc::RecvTimeoutError::Timeout) => {\n                    anyhow::bail!(\"SQLite connection open timed out after {} seconds\", capped);\n                }\n                Err(mpsc::RecvTimeoutError::Disconnected) => {\n                    anyhow::bail!(\"SQLite open thread exited unexpectedly\");\n                }\n            }\n        } else {\n            Connection::open(&path_buf).context(\"SQLite failed to open database\")?\n        };\n\n        Ok(conn)\n    }\n\n    /// Initialize all tables: memories, FTS5, `embedding_cache`\n    fn init_schema(conn: &Connection) -> anyhow::Result<()> {\n        fn is_db_locked_error(e: &rusqlite::Error) -> bool {\n            use rusqlite::ffi::ErrorCode;\n            matches!(\n                e,","sourceCodeStart":135,"sourceCodeEnd":171,"githubUrl":"https://github.com/zeroclaw-labs/zeroclaw/blob/88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc/crates/zeroclaw-memory/src/sqlite.rs#L135-L171","documentation":"open_connection() optionally runs Connection::open on a helper thread and waits with recv_timeout, clamped to SQLITE_OPEN_TIMEOUT_CAP_SECS. If the timer expires (open blocking on a locked database file or a stalled filesystem), the thread is abandoned and this error reports the capped seconds — which may be lower than the configured value.","triggerScenarios":"Another process holds workspace/memory/brain.db (a second gateway instance or stray daemon); the database lives on NFS/SMB where POSIX locks hang; very slow or failing storage; the configured timeout exceeds the internal cap.","commonSituations":"Two zeroclaw instances on one workspace; Docker bind-mounts on macOS/Windows with slow I/O; antivirus or indexers holding brain.db; NFS home directories.","solutions":["Find and stop the other holder: lsof <workspace>/memory/brain.db (check the -wal/-shm files too)","Raise the sqlite open timeout setting — but note it is clamped to SQLITE_OPEN_TIMEOUT_CAP_SECS, so values beyond the cap won't help","Move the workspace (or at least brain.db) to fast local storage, not NFS/SMB","If a dead process left stale locks, verify nothing is running, remove brain.db-wal and brain.db-shm, and retry"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// Before startup, detect another live holder of the database\n// (shell): lsof <workspace>/memory/brain.db ; return non-zero output -> refuse to start\nlet locked = std::process::Command::new(\"lsof\").arg(db_path).output()?.status.success();","typeGuard":"fn is_sqlite_open_timeout(e: &anyhow::Error) -> bool {\n    e.to_string().starts_with(\"SQLite connection open timed out\")\n}","tryCatchPattern":"for attempt in 0..3 {\n    match SqliteMemory::new(ws, timeout).await {\n        Ok(m) => break Ok(m),\n        Err(e) if is_sqlite_open_timeout(&e) && attempt < 2 => { free_locks_or_wait(); }\n        Err(e) => break Err(e),\n    }\n}","preventionTips":["Run exactly one gateway instance per workspace","Keep brain.db on local disk, never NFS/SMB","Set the sqlite open timeout with the internal cap in mind","Exclude brain.db* from antivirus/indexer scans"],"tags":["sqlite","database-lock","timeout","filesystem","rust"],"backgroundTag":"database-connection-timeout","analyzedSha":"88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc","analyzedAt":"2026-08-23T01:07:41.857Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}