{"record":{"id":"13fc202d99b59fee","repo":"BigPizzaV3/CodexPlusPlus","slug":"unexpected-monitor-lock-type","errorCode":null,"errorMessage":"Unexpected monitor lock type","messagePattern":"Unexpected monitor lock type","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/codex-plus-core/src/native_browser.rs","lineNumber":739,"sourceCode":"fn acquire_monitor_owner(paths: &BrowserPaths) -> Result<File> {\n    plain_path(&paths.state_root)?;\n    ensure!(\n        !paths.state_root.starts_with(&paths.runtime_root),\n        \"Backups must be outside the cache\"\n    );\n    fs::create_dir_all(&paths.state_root)?;\n    let path = paths.state_root.join(\"monitor.lock\");\n    let _guards = pin_parents(&path)?;\n    let mut options = OpenOptions::new();\n    options.read(true).write(true).create(true).truncate(false);\n    #[cfg(windows)]\n    {\n        use std::os::windows::fs::OpenOptionsExt;\n        options.share_mode(0x1 | 0x2).custom_flags(0x00200000);\n    }\n    let owner = options.open(&path)?;\n    let meta = owner.metadata()?;\n    ensure!(meta.is_file(), \"Unexpected monitor lock type\");\n    #[cfg(windows)]\n    {\n        use std::os::windows::fs::MetadataExt;\n        ensure!(meta.file_attributes() & 0x400 == 0, \"Monitor lock is a reparse point\");\n    }\n    plain_path(&path)?;\n    owner.try_lock_exclusive().context(\"Another native browser monitor is active\")?;\n    Ok(owner)\n}\n\n/// Called after Codex has been stopped, before the manager launches a replacement.\n/// Never restores files itself or creates a lock for an older launcher.\npub fn wait_for_monitor_shutdown(timeout: Duration) -> Result<()> {\n    if !cfg!(windows) {\n        return Ok(());\n    }\n    let paths = BrowserPaths::current()?;\n    wait_for_monitor_shutdown_at(&paths, timeout)","sourceCodeStart":721,"sourceCodeEnd":757,"githubUrl":"https://github.com/BigPizzaV3/CodexPlusPlus/blob/b1ed92e5e4a2d74095d4b8db5af43cef7acba9c6/crates/codex-plus-core/src/native_browser.rs#L721-L757","documentation":"acquire_monitor_owner opens (or creates) the file `<state_root>/monitor.lock`, which is used as an exclusive advisory lock to ensure only one native browser monitor runs. Before locking, it validates that the path is a regular file. This ensure! fires when the filesystem object at that path is not a regular file (e.g. a directory, FIFO, device node, or symlink target resolving to something else), so the library refuses to use it as a lock and aborts startup.","triggerScenarios":"Calling start_monitor_with_contract (via the manager's monitor start flow) when `<state_root>/monitor.lock` exists but is not a regular file — e.g. someone created a directory named monitor.lock, the path was replaced by a named pipe/socket, or a symlink/device node was placed there.","commonSituations":"A leftover or malicious file in the CodexPlusPlus state directory; backup/restore tools or sync clients (Dropbox, OneDrive) replacing the lock with a non-file object; a user or script manually creating `monitor.lock` as a directory; container/overlay filesystems materializing the path oddly.","solutions":["Inspect `<state_root>/monitor.lock` (`ls -la` / `file` on it) to see what it actually is.","Delete the bogus object (after confirming it is not a real file you need) and let the library recreate it on next start.","Verify the state_root points at the intended CodexPlusPlus state directory, not a directory shared with other tooling or cloud sync.","Re-run the monitor start; if it recurs, check for software on the machine that creates symlinks/pipes at that path (security software, tampering)."],"exampleFix":"// before (manual state dir)\nmkdir ~/.codexplusplus-state/monitor.lock\n// after\nrm -rf ~/.codexplusplus-state/monitor.lock  # replace non-file object with nothing; library recreates it","handlingStrategy":"validation","validationCode":"let lock = state_root.join(\"monitor.lock\");\nif lock.symlink_metadata().is_ok() && !lock.symlink_metadata().unwrap().is_file() {\n    // non-file object at lock path: remove it or refuse to start the monitor\n    std::fs::remove_file(&lock)?; // only after confirming it's safe to delete\n}","typeGuard":"fn is_regular_file(p: &std::path::Path) -> bool {\n    std::fs::symlink_metadata(p).map(|m| m.is_file()).unwrap_or(false)\n}","tryCatchPattern":"match native_browser::start_monitor(paths, enabled) {\n    Err(e) if e.to_string().contains(\"Unexpected monitor lock type\") => {\n        // clear the bogus lock object and retry once\n    }\n    other => other?,\n}","preventionTips":["Keep the state root on a plain local filesystem, not one managed by sync clients or shared with other tools","Never create files named monitor.lock yourself; let the library own that path","Before starting the monitor, assert the state root contains only expected regular files"],"tags":["filesystem","lock-file","path-validation"],"backgroundTag":"incompatible-source-type","analyzedSha":"b1ed92e5e4a2d74095d4b8db5af43cef7acba9c6","analyzedAt":"2026-09-19T23:35:21.129Z","contentChangedAt":"2026-09-19T23:35:21.129Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}