{"record":{"id":"99f6438dfce79dac","repo":"Hmbown/CodeWhale","slug":"could-not-securely-open-error","errorCode":null,"errorMessage":"could not securely open {}: {error}","messagePattern":"could not securely open (.+?): (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/lib.rs","lineNumber":3023,"sourceCode":"#[cfg(not(any(unix, windows)))]\nfn workspace_dotenv_has_multiple_links(\n    _file: &std::fs::File,\n    _metadata: &std::fs::Metadata,\n) -> Result<bool> {\n    Ok(false)\n}\n\n#[cfg(unix)]\nfn open_workspace_dotenv_without_following_links(path: &Path) -> Result<std::fs::File> {\n    use std::os::unix::fs::OpenOptionsExt;\n\n    std::fs::OpenOptions::new()\n        .read(true)\n        // `O_NONBLOCK` is inert for regular files but prevents a FIFO named\n        // `.env` from hanging startup before the metadata check can reject it.\n        .custom_flags(libc::O_CLOEXEC | libc::O_NOFOLLOW | libc::O_NONBLOCK)\n        .open(path)\n        .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!(","sourceCodeStart":3005,"sourceCodeEnd":3041,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/lib.rs#L3005-L3041","documentation":"The Unix open path for the workspace `.env` uses `O_NOFOLLOW | O_CLOEXEC | O_NONBLOCK` so symlinks are never followed and a FIFO named `.env` cannot hang startup. If `open` fails (including the ELOOP that O_NOFOLLOW produces for symlinks) it is wrapped in this error.","triggerScenarios":"`OpenOptions::open(path)` returns an io::Error: `ELOOP` (path is a symlink, rejected by O_NOFOLLOW), `ENOENT` (missing file), `EACCES` (permissions), or a non-regular file type.","commonSituations":"A `.env` that is actually a symlink (common when people symlink shared dotfiles), or one unreadable due to permissions/ownership.","solutions":["Replace the `.env` symlink with a real regular file copy inside the workspace.","Fix file permissions so the running user can read it.","Create the file if it is missing, or unset the expectation of a workspace `.env` for this project."],"exampleFix":"// before (shell)\nln -s ~/secrets/.env .env\n// after\ncp ~/secrets/.env .env && chmod 600 .env","handlingStrategy":"validation","validationCode":"let md = std::fs::symlink_metadata(\".env\")?;\nif md.file_type().is_symlink() {\n    eprintln!(\".env must be a regular file, not a symlink\");\n}\nif !md.is_file() { eprintln!(\".env is not a regular file\"); }","typeGuard":"fn is_safe_dotenv(path: &Path) -> bool {\n    std::fs::symlink_metadata(path)\n        .map(|md| md.is_file())\n        .unwrap_or(false)\n}","tryCatchPattern":"match load_workspace_dotenv_credentials_from_path(&path) {\n    Err(e) if e.to_string().contains(\"could not securely open\") => {\n        eprintln!(\".env must be a readable regular file (no symlinks): {e:#}\");\n    }\n    other => other?,\n}","preventionTips":["Copy shared dotfiles into the workspace instead of symlinking `.env`.","Set restrictive permissions (`chmod 600 .env`) and correct ownership.","Verify with `ls -la .env` that it is a regular file before launching."],"tags":["filesystem","security","symlink","dotenv"],"backgroundTag":"file-open-failed","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"}