{"record":{"id":"3f0e48375d6ea8e1","repo":"Hmbown/CodeWhale","slug":"is-a-reparse-point-not-a-workspace-owned-file","errorCode":null,"errorMessage":"{} is a reparse point, not a workspace-owned file","messagePattern":"(.+?) is a reparse point, not a workspace-owned file","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/tui/src/lib.rs","lineNumber":2721,"sourceCode":"        .map_err(|error| anyhow!(\"could not securely open {}: {error}\", path.display()))\n}\n\n#[cfg(windows)]\nfn open_workspace_dotenv_without_following_links(path: &Path) -> Result<std::fs::File> {\n    use std::os::windows::fs::{MetadataExt, OpenOptionsExt};\n\n    const FILE_ATTRIBUTE_REPARSE_POINT: u32 = 0x0000_0400;\n    const FILE_FLAG_OPEN_REPARSE_POINT: u32 = 0x0020_0000;\n    let file = std::fs::OpenOptions::new()\n        .read(true)\n        .custom_flags(FILE_FLAG_OPEN_REPARSE_POINT)\n        .open(path)\n        .map_err(|error| anyhow!(\"could not securely open {}: {error}\", path.display()))?;\n    let metadata = file\n        .metadata()\n        .map_err(|error| anyhow!(\"could not inspect {}: {error}\", path.display()))?;\n    if metadata.file_attributes() & FILE_ATTRIBUTE_REPARSE_POINT != 0 {\n        bail!(\n            \"{} is a reparse point, not a workspace-owned file\",\n            path.display()\n        );\n    }\n    Ok(file)\n}\n\n#[cfg(not(any(unix, windows)))]\nfn open_workspace_dotenv_without_following_links(path: &Path) -> Result<std::fs::File> {\n    let metadata = std::fs::symlink_metadata(path)\n        .map_err(|error| anyhow!(\"could not inspect {}: {error}\", path.display()))?;\n    if metadata.file_type().is_symlink() {\n        bail!(\n            \"{} is a symbolic link, not a workspace-owned file\",\n            path.display()\n        );\n    }\n    std::fs::File::open(path)","sourceCodeStart":2703,"sourceCodeEnd":2739,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/0c42157ee52f9d55af2b506d71b46249910f77d3/crates/tui/src/lib.rs#L2703-L2739","documentation":"Windows variant of the anti-symlink rule: open_workspace_dotenv_without_following_links opens .env with FILE_FLAG_OPEN_REPARSE_POINT and then checks FILE_ATTRIBUTE_REPARSE_POINT in the metadata. If the bit is set, the entry is a reparse point — a symlink, junction, or cloud-sync placeholder — rather than a workspace-owned regular file, and the credential load is refused.","triggerScenarios":"Workspace .env replaced by a Windows symlink or junction (mklink); OneDrive/style cloud-sync placeholders materializing .env as a reparse point; enterprise folder-redirection turning workspace files into reparse points.","commonSituations":"Developer workspaces under OneDrive/SharePoint sync; linking .env to a shared secrets file with mklink; CI agents with redirected profiles.","solutions":["Recreate .env as a plain file (delete the link, write a real file)","Move the workspace out of cloud-sync-managed or placeholder-enabled folders, or exclude .env from placeholder conversion","Do not link .env; each workspace keeps its own literal file"],"exampleFix":":: before\ndir /a .env      # shows <SYMLINK> or reparse info\n\n:: after\ndel .env\necho KEY=value> .env\ndir /a .env      # plain file","handlingStrategy":"validation","validationCode":":: Windows: refuse reparse points before launch\nfsutil reparsepoint query .env >nul 2>&1 && (echo .env is a reparse point & exit /b 2)\ndir /a .env | findstr /i \"JUNCTION SYMLINK\" >nul && (echo .env is a link & exit /b 2)","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep workspaces out of OneDrive/cloud-sync placeholder paths, or exclude .env","Never `mklink` .env to a shared secrets file","Recreate .env as a plain file after sync incidents"],"tags":["dotenv","security","windows","reparse-point"],"backgroundTag":"symlink-security-check","analyzedSha":"0c42157ee52f9d55af2b506d71b46249910f77d3","analyzedAt":"2026-08-20T21:50:45.477Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}