{"record":{"id":"b28dd802dc028fb9","repo":"BigPizzaV3/CodexPlusPlus","slug":"unexpected-observation-path","errorCode":null,"errorMessage":"Unexpected observation path","messagePattern":"Unexpected observation path","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/codex-plus-core/src/native_browser.rs","lineNumber":947,"sourceCode":"    }\n    for key in keys {\n        let runtime = paths.runtime_root.join(key);\n        files.insert(runtime.join(SERVICE));\n        for (file, _) in RuntimeContract::pinned().files {\n            files.insert(runtime.join(file));\n        }\n    }\n    let mut hash = Sha256::new();\n    for path in files {\n        plain_path(&path)?;\n        hash.update(path.to_string_lossy().as_bytes());\n        if !path.exists() {\n            hash.update(b\"missing\");\n            continue;\n        }\n        let file = File::open(&path)?;\n        let meta = file.metadata()?;\n        ensure!(meta.is_file(), \"Unexpected observation path\");\n        hash.update(format!(\n            \"{:?}:{:?}:{}\",\n            meta.created()?,\n            meta.modified()?,\n            meta.len()\n        ));\n        #[cfg(windows)]\n        {\n            use std::os::windows::io::AsRawHandle;\n            use windows::Win32::Foundation::HANDLE;\n            use windows::Win32::Storage::FileSystem::{\n                BY_HANDLE_FILE_INFORMATION, GetFileInformationByHandle,\n            };\n            let mut identity = BY_HANDLE_FILE_INFORMATION::default();\n            unsafe {\n                GetFileInformationByHandle(HANDLE(file.as_raw_handle()), &mut identity)?;\n            }\n            ensure!(","sourceCodeStart":929,"sourceCodeEnd":965,"githubUrl":"https://github.com/BigPizzaV3/CodexPlusPlus/blob/b1ed92e5e4a2d74095d4b8db5af43cef7acba9c6/crates/codex-plus-core/src/native_browser.rs#L929-L965","documentation":"During observation hashing, each path expected to be a regular file is opened and metadata-checked; if metadata shows the path is not a plain file (directory, socket, symlink target, device), this error is thrown. It protects the observation fingerprint from being computed over non-file entries whose metadata would be meaningless.","triggerScenarios":"monitor_once / idle observation runs hash a collected file path; path.exists() is true but file.metadata().is_file() returns false — e.g. a directory or special file appeared where observation records expect a regular file.","commonSituations":"A directory was created inside the observation set (mkdir instead of file write); a FIFO/socket/device node was placed in the watched directory; a symlink to a directory survived earlier checks; OS-specific special files in the runtime dir.","solutions":["Inspect the observation directory and remove/replace the non-regular-file entry with a normal file","Log which path failed (wrap the ensure! with the path in the message) to identify the offending entry","Filter non-regular entries during directory collection (skip !meta.is_file()) instead of erroring","Check whether another process (editor temp files, sync daemons) creates directories/symlinks in the watched path"],"exampleFix":"// before\nensure!(meta.is_file(), \"Unexpected observation path\");\n// after\nensure!(meta.is_file(), \"Unexpected observation path: {}\", path.display());\n// or skip non-files:\nif !meta.is_file() { continue; }","handlingStrategy":"validation","validationCode":"const stat = fs.lstatSync(p);\nif (!stat.isFile()) throw new Error(`observation path is not a regular file: ${p}`);","typeGuard":"const isRegularFile = (p: string): boolean => { try { return fs.statSync(p).isFile(); } catch { return false; } };","tryCatchPattern":"match observe_and_hash() {\n    Err(e) if e.to_string().contains(\"Unexpected observation path\") => {\n        eprintln!(\"non-file entry in observation set; rescan after cleanup\");\n        cleanup_and_retry()\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Only write regular files into watched/observation directories","Exclude symlinks, directories and special files when collecting paths","Avoid letting sync daemons or editors create temp dirs inside watched paths"],"tags":["filesystem","observation","metadata","hashing"],"backgroundTag":"path-is-not-a-directory","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"}