{"record":{"id":"24c86617c909dc0f","repo":"Hmbown/CodeWhale","slug":"private-sidecar-file-path-must-be-a-non-reparse-regular-file","errorCode":null,"errorMessage":"private sidecar file {path} must be a non-reparse regular file","messagePattern":"private sidecar file (.+?) must be a non-reparse regular file","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/session_manager.rs","lineNumber":212,"sourceCode":"                \"private sidecar file {} must be one regular filesystem link\",\n                path.display()\n            ),\n        ));\n    }\n    Ok(())\n}\n\n#[cfg(windows)]\nfn validate_private_regular_file(file: &fs::File, path: &Path) -> io::Result<()> {\n    use std::os::windows::fs::MetadataExt as _;\n    use std::os::windows::io::AsRawHandle as _;\n    use windows_sys::Win32::Storage::FileSystem::{\n        BY_HANDLE_FILE_INFORMATION, FILE_ATTRIBUTE_REPARSE_POINT, GetFileInformationByHandle,\n    };\n\n    let metadata = file.metadata()?;\n    if !metadata.is_file() || metadata.file_attributes() & FILE_ATTRIBUTE_REPARSE_POINT != 0 {\n        return Err(io::Error::new(\n            io::ErrorKind::InvalidData,\n            format!(\n                \"private sidecar file {} must be a non-reparse regular file\",\n                path.display()\n            ),\n        ));\n    }\n    let mut info = BY_HANDLE_FILE_INFORMATION::default();\n    // SAFETY: `file` keeps the handle valid and `info` is writable for the call.\n    if unsafe { GetFileInformationByHandle(file.as_raw_handle(), &mut info) } == 0 {\n        return Err(io::Error::last_os_error());\n    }\n    if info.nNumberOfLinks != 1 {\n        return Err(io::Error::new(\n            io::ErrorKind::InvalidData,\n            format!(\n                \"private sidecar file {} must have exactly one filesystem link\",\n                path.display()","sourceCodeStart":194,"sourceCodeEnd":230,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/session_manager.rs#L194-L230","documentation":"On Windows, session_manager validates that a private sidecar file (lock or read file) is a regular file that is not a reparse point before use. Reparse points (symlinks, junctions, mount points) could redirect the private file elsewhere, which is rejected to protect session data integrity. Any path that resolves through a reparse point, or is not a regular file, yields this InvalidData error.","triggerScenarios":"Calling open_private_lock_file or open_private_read_file on Windows with a path whose metadata is not is_file(), or whose file attributes include FILE_ATTRIBUTE_REPARSE_POINT (symlink, junction, OneDrive placeholder, Dev Drive/ProjFS file).","commonSituations":"The session directory or sidecar file was replaced with a symlink or junction; files live under OneDrive/cloud placeholder sync; a project filter (ProjFS) or Dev Drive reparse file is in the sessions directory; a backup/restore tool substituted links for real files.","solutions":["Remove the symlink/junction and replace it with a real regular file (copy the target back).","Run the session store on a local path not managed by OneDrive/Dropbox placeholders or ProjFS.","Exclude the sessions directory from tools that convert files to reparse points (backup, dedupe, cloud sync).","Verify with `fsutil reparsepoint query <path>` (Windows) whether the file is a reparse point."],"exampleFix":"// before: sessions dir is a junction to a network share\nmklink /J %APPDATA%\\codewhale\\sessions \\\\server\\share\\sessions\n// after: use a real local directory\nmkdir %APPDATA%\\codewhale\\sessions","handlingStrategy":"validation","validationCode":"// Windows: check before opening\nconst FILE_ATTRIBUTE_REPARSE_POINT: u32 = 0x400;\nlet md = std::fs::metadata(path)?;\nif !md.is_file() || md.file_attributes() & FILE_ATTRIBUTE_REPARSE_POINT != 0 {\n    return Err(format!(\"{} must be a regular non-reparse file\", path.display()));\n}","typeGuard":"fn is_plain_regular_file(p: &Path) -> bool {\n    std::fs::metadata(p).map(|m| m.is_file() && m.file_attributes() & 0x400 == 0).unwrap_or(false)\n}","tryCatchPattern":"match open_private_lock_file(path) {\n    Err(e) if e.kind() == std::io::ErrorKind::InvalidData => eprintln!(\"sidecar is a link or special file: {e}\"),\n    other => other?,\n}","preventionTips":["Keep the session store on a plain local NTFS directory.","Exclude the sessions dir from OneDrive/sync and ProjFS.","Do not symlink or junction files inside the session directory."],"tags":["windows","filesystem","io"],"backgroundTag":"incompatible-source-type","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}