{"record":{"id":"3ad227f69d7b9ca0","repo":"Hmbown/CodeWhale","slug":"automation-lock-must-be-a-regular-file","errorCode":null,"errorMessage":"Automation lock must be a regular file","messagePattern":"Automation lock must be a regular file","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/tui/src/automation_manager.rs","lineNumber":1023,"sourceCode":"        options.create(true).truncate(false).read(true).write(true);\n        #[cfg(unix)]\n        {\n            use std::os::unix::fs::OpenOptionsExt as _;\n            options\n                .mode(0o600)\n                .custom_flags(libc::O_NOFOLLOW | libc::O_CLOEXEC);\n        }\n        #[cfg(windows)]\n        {\n            use std::os::windows::fs::OpenOptionsExt as _;\n            options.custom_flags(0x0020_0000); // FILE_FLAG_OPEN_REPARSE_POINT\n        }\n        let file = options\n            .open(&path)\n            .with_context(|| format!(\"open {}\", path.display()))?;\n        let metadata = file.metadata()?;\n        if !metadata.is_file() {\n            bail!(\"Automation lock must be a regular file\");\n        }\n        #[cfg(unix)]\n        {\n            use std::os::unix::fs::MetadataExt as _;\n            if metadata.nlink() != 1 {\n                bail!(\"Automation lock must not have hard links\");\n            }\n        }\n        #[cfg(windows)]\n        {\n            use std::os::windows::fs::MetadataExt as _;\n            if metadata.file_attributes() & 0x400 != 0 {\n                bail!(\"Automation lock must not be a reparse point\");\n            }\n        }\n        Ok(fd_lock::RwLock::new(file))\n    }\n","sourceCodeStart":1005,"sourceCodeEnd":1041,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/automation_manager.rs#L1005-L1041","documentation":"The automation manager opens its lock file with strict options and verifies via metadata that it is a regular file before wrapping it in an fd_lock RwLock. Directories, devices, FIFOs, or symlinks resolving to non-regular files are rejected to keep the lock semantics safe. (Note: because options.open follows symlinks, a symlink pointing at a regular file passes this check.)","triggerScenarios":"The configured automation lock path exists but is a directory, a device node, a FIFO/socket, or otherwise not a regular file when the lock is opened.","commonSituations":"Lock path misconfigured to a directory; a stale mount or tmpfs artifact at the path; creating a FIFO/device at the expected location; container volume mounting a directory over the lock file path.","solutions":["Remove the non-regular file at the lock path (rm the directory/FIFO) and let the manager recreate it as a regular file","Point the lock-file config at a correct, dedicated file path in a writable directory","Check what is mounted at that path (mount/ls -l) if running in a container"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"let meta = std::fs::metadata(&lock_path)?;\nassert!(meta.is_file(), \"automation lock path must be a regular file\");","typeGuard":null,"tryCatchPattern":"match result {\n    Err(e) if e.to_string().contains(\"must be a regular file\") => {\n        std::fs::remove_file(&lock_path).ok(); // recreate lock\n        // retry once\n    }\n    r => r?,\n}","preventionTips":["Keep the lock path dedicated — do not point it at directories or device nodes","Check ls -l at the path after container/volume changes","Recreate the lock file if external tools created odd entries there"],"tags":["filesystem","lock","validation"],"backgroundTag":"invalid-state-transition","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-23T02:17:17.105Z"}