{"record":{"id":"92168e7cbbbf9042","repo":"Hmbown/CodeWhale","slug":"skill-state-lock-at-must-be-a-regular-file","errorCode":null,"errorMessage":"skill state lock at {} must be a regular file","messagePattern":"skill state lock at (.+?) must be a regular file","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/skill_state.rs","lineNumber":238,"sourceCode":"#[cfg(windows)]\nfn validate_state_lock(path: &Path, file: &fs::File) -> Result<()> {\n    use std::os::windows::fs::MetadataExt as _;\n\n    const FILE_ATTRIBUTE_REPARSE_POINT: u32 = 0x0000_0400;\n    let metadata = file\n        .metadata()\n        .with_context(|| format!(\"inspect skill state lock at {}\", path.display()))?;\n    anyhow::ensure!(\n        metadata.is_file() && metadata.file_attributes() & FILE_ATTRIBUTE_REPARSE_POINT == 0,\n        \"skill state lock at {} must be a regular, non-reparse file\",\n        path.display()\n    );\n    Ok(())\n}\n\n#[cfg(all(not(unix), not(windows)))]\nfn validate_state_lock(path: &Path, file: &fs::File) -> Result<()> {\n    anyhow::ensure!(\n        file.metadata()\n            .with_context(|| format!(\"inspect skill state lock at {}\", path.display()))?\n            .is_file(),\n        \"skill state lock at {} must be a regular file\",\n        path.display()\n    );\n    Ok(())\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n    use tempfile::TempDir;\n\n    fn fresh() -> (TempDir, SkillStateStore) {\n        let dir = TempDir::new().unwrap();\n        let path = dir.path().join(STATE_FILE_NAME);\n        let store = SkillStateStore::load_from(path).unwrap();","sourceCodeStart":220,"sourceCodeEnd":256,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/433685b2024e7bc4c99e1e2e326bcad39b4d9d65/crates/tui/src/skill_state.rs#L220-L256","documentation":"On platforms other than Unix and Windows, validate_state_lock checks only that the lock file's metadata reports it is a regular file. If the path resolves to a directory, FIFO, device, or other special file, the ensure! fails. Like its platform-specific siblings, this guards the integrity of the skill state lock.","triggerScenarios":"open_state_lock runs on a non-Unix/non-Windows platform (e.g. wasm or another target) and the lock file at the given path is not a regular file.","commonSituations":"Running on an unusual target (embedded, wasm, custom platform) where the lock path was pre-created as a directory or special node, or stale/corrupted state left by another tool.","solutions":["Delete the lock path so the application can recreate it as a regular file.","Verify what exists at the path (`ls -la`) and remove any directory/FIFO/device node found there.","Run on a supported mainstream platform if the target's filesystem semantics are unknown."],"exampleFix":"// before\n$ ls ~/.codewhale/skill-state.lock\ndirectory\n// after\n$ rm -rf ~/.codewhale/skill-state.lock\n$ codewhale  # recreates a regular lock file","handlingStrategy":"validation","validationCode":"let md = std::fs::metadata(lock_path)?;\nif !md.is_file() {\n    std::fs::remove_file(lock_path).or_else(|_| std::fs::remove_dir_all(lock_path))?;\n}","typeGuard":"fn is_regular_file(p: &std::path::Path) -> bool {\n    std::fs::metadata(p).map(|m| m.is_file()).unwrap_or(false)\n}","tryCatchPattern":null,"preventionTips":["Keep the skill state directory on a filesystem that supports regular files only (no special nodes).","Delete stale lock paths after crashes or state resets.","Avoid creating the lock path manually or via scripts that may mkdir it."],"tags":["filesystem","platform","lockfile"],"backgroundTag":"incompatible-source-type","analyzedSha":"433685b2024e7bc4c99e1e2e326bcad39b4d9d65","analyzedAt":"2026-09-15T12:24:24.634Z","contentChangedAt":"2026-09-15T12:24:24.634Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}