{"record":{"id":"eeaeb452495e1ab0","repo":"Hmbown/CodeWhale","slug":"this-runtime-is-already-active-in-another-process-close-the","errorCode":null,"errorMessage":"This runtime is already active in another process. Close the other Codewhale session and try again, or set CODEWHALE_RUNTIME_DIR to a different directory.","messagePattern":"This runtime is already active in another process\\. Close the other Codewhale session and try again, or set CODEWHALE_RUNTIME_DIR to a different directory\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/runtime_threads.rs","lineNumber":4204,"sourceCode":"            options.create(true).truncate(false).read(true).write(true);\n        })?;\n        #[cfg(unix)]\n        {\n            use std::os::unix::fs::PermissionsExt as _;\n            file.set_permissions(fs::Permissions::from_mode(0o600))\n                .context(\"Failed to protect Runtime process owner lock\")?;\n        }\n        // Same-process drop-then-reopen can observe WouldBlock for a brief\n        // window while the previous fd is still closing — the same close-\n        // release race #5735 hit on the Runtime Chat scope lock. Retry only\n        // that contention; a lock that stays held still belongs to its owner.\n        let deadline = Instant::now() + Duration::from_millis(25);\n        loop {\n            match Self::try_lock_exclusive(&file) {\n                Ok(()) => break,\n                Err(error) if Self::is_contention(&error) => {\n                    if Instant::now() >= deadline {\n                        bail!(\"{RUNTIME_PROCESS_OWNER_LOCK_HELD}\");\n                    }\n                    std::thread::yield_now();\n                    std::thread::sleep(Duration::from_millis(1));\n                }\n                Err(error) => {\n                    return Err(error).context(\"Failed to acquire Runtime process owner lock\");\n                }\n            }\n        }\n        Ok(Self { _file: file })\n    }\n\n    fn is_contention(error: &std::io::Error) -> bool {\n        error.kind() == std::io::ErrorKind::WouldBlock\n            || matches!(error.raw_os_error(), Some(32 | 33))\n    }\n\n    fn try_lock_exclusive(file: &File) -> std::io::Result<()> {","sourceCodeStart":4186,"sourceCodeEnd":4222,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/433685b2024e7bc4c99e1e2e326bcad39b4d9d65/crates/tui/src/runtime_threads.rs#L4186-L4222","documentation":"The Runtime takes an exclusive OS file lock (the process owner lock) to guarantee a single active Codewhale runtime per runtime directory. try_lock_exclusive is retried for ~25ms; if the lock is still contended, it bails with RUNTIME_PROCESS_OWNER_LOCK_HELD. This means another live process owns the same CODEWHALE_RUNTIME_DIR.","triggerScenarios":"Starting a second Codewhale session pointed at the same runtime directory while a previous session is still running (or its lock file was left behind by a hung process); launching the CLI and TUI simultaneously on the same CODEWHALE_RUNTIME_DIR.","commonSituations":"Two terminal tabs running Codewhale in the same project; a crashed session whose lock was never released; CI jobs sharing a HOME/runtime dir; container without per-job runtime dirs.","solutions":["Close the other running Codewhale session holding the lock, then retry","Set CODEWHALE_RUNTIME_DIR to a different directory for the second session","Find and terminate the stale owner process (inspect the lock file's owner PID), or remove the stale lock file if the owner is confirmed dead"],"exampleFix":"// before\nCODEWHALE_RUNTIME_DIR=~/.codewhale/runtime codewhale tui  # conflicts with running session\n// after\nCODEWHALE_RUNTIME_DIR=~/.codewhale/runtime-work codewhale tui","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":["Unique CODEWHALE_RUNTIME_DIR per session"],"tags":["locking","concurrency","process"],"backgroundTag":"address-already-in-use","analyzedSha":"433685b2024e7bc4c99e1e2e326bcad39b4d9d65","analyzedAt":"2026-09-15T12:24:24.634Z","contentChangedAt":"2026-09-15T12:24:24.634Z","schemaVersion":2},"datasetVersion":"2026-09-22T01:17:13.364Z"}