{"record":{"id":"81474622bd904914","repo":"Hmbown/CodeWhale","slug":"is-a-symbolic-link-not-a-workspace-owned-file","errorCode":null,"errorMessage":"{} is a symbolic link, not a workspace-owned file","messagePattern":"(.+?) is a symbolic link, not a workspace-owned file","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/tui/src/lib.rs","lineNumber":2734,"sourceCode":"        .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)\n        .map_err(|error| anyhow!(\"could not securely open {}: {error}\", path.display()))\n}\n\n/// Generate shell completions for the given shell\nfn generate_completions(shell: Shell) {\n    let mut cmd = Cli::command();\n    let name = cmd.get_name().to_string();\n    generate(shell, &mut cmd, name, &mut io::stdout());\n}\n\n/// Run the offline evaluation harness (no network/LLM calls).\nfn run_eval(args: EvalArgs) -> Result<()> {\n    let fail_step = match args.fail_step.as_deref() {","sourceCodeStart":2716,"sourceCodeEnd":2752,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/0c42157ee52f9d55af2b506d71b46249910f77d3/crates/tui/src/lib.rs#L2716-L2752","documentation":"Fallback implementation of the no-symlink contract for platforms that are neither unix nor windows: open_workspace_dotenv_without_following_links stats .env with symlink_metadata (lstat semantics) and refuses the load if the entry itself is a symbolic link, then opens the file normally. Same ownership rule as the unix/windows paths, expressed portably.","triggerScenarios":"Running on a non-unix, non-windows target (for example wasi or another tier-3 platform) where the workspace .env is a symbolic link to another file.","commonSituations":"Exotic embedder/test targets; workspace setups that symlink dotfiles from a central store, ported to unusual platforms.","solutions":["Replace the symlink with a real file containing the literal values","Keep per-workspace literal .env files instead of symlinking a shared one"],"exampleFix":"# before\nls -l .env       # .env -> /shared/secrets.env\n\n# after\ncp -L /shared/secrets.env .env   # real file, literal values","handlingStrategy":"validation","validationCode":"# Portable pre-check: entry must not itself be a symlink\n[ ! -L .env ] || { echo '.env is a symbolic link; replace with a real file'; exit 2; }","typeGuard":"fn env_not_symlink(path: &Path) -> bool {\n    !std::fs::symlink_metadata(path)\n        .map(|m| m.file_type().is_symlink())\n        .unwrap_or(true)\n}","tryCatchPattern":null,"preventionTips":["Copy secrets into a per-workshop literal .env instead of symlinking","Verify with ls -l that .env is not an arrow (`->`) entry"],"tags":["dotenv","security","symlink","filesystem"],"backgroundTag":"symlink-security-check","analyzedSha":"0c42157ee52f9d55af2b506d71b46249910f77d3","analyzedAt":"2026-08-20T21:50:45.477Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}