{"record":{"id":"3f0991a5cb3bef0b","repo":"Hmbown/CodeWhale","slug":"is-not-a-regular-file","errorCode":null,"errorMessage":"{} is not a regular file","messagePattern":"(.+?) is not a regular file","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/tui/src/lib.rs","lineNumber":2622,"sourceCode":"        }\n        if ch == '#' && !double_quoted {\n            comment = true;\n            continue;\n        }\n        if ch == '$' {\n            return true;\n        }\n    }\n    false\n}\n\nfn read_stable_workspace_dotenv(path: &Path) -> Result<Vec<u8>> {\n    let mut file = open_workspace_dotenv_without_following_links(path)?;\n    let metadata = file\n        .metadata()\n        .map_err(|error| anyhow!(\"could not inspect {}: {error}\", path.display()))?;\n    if !metadata.is_file() {\n        bail!(\"{} is not a regular file\", path.display());\n    }\n    if workspace_dotenv_has_multiple_links(&file, &metadata)? {\n        bail!(\n            \"{} has multiple filesystem links, not a unique workspace-owned file\",\n            path.display()\n        );\n    }\n    if metadata.len() > MAX_WORKSPACE_DOTENV_BYTES {\n        bail!(\n            \"{} exceeds the {} byte workspace .env limit\",\n            path.display(),\n            MAX_WORKSPACE_DOTENV_BYTES\n        );\n    }\n\n    let mut contents = Vec::with_capacity(metadata.len() as usize);\n    (&mut file)\n        .take(MAX_WORKSPACE_DOTENV_BYTES + 1)","sourceCodeStart":2604,"sourceCodeEnd":2640,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/0c42157ee52f9d55af2b506d71b46249910f77d3/crates/tui/src/lib.rs#L2604-L2640","documentation":"read_stable_workspace_dotenv opens the workspace .env without following symlinks and immediately checks the fstat metadata of what it opened. If the entry is not a regular file — a FIFO, socket, device, or directory — the load is refused: only a plain regular file is an acceptable workspace-owned credential source, because non-regular files can block, stream, or masquerade.","triggerScenarios":"Workspace .env replaced by a named pipe (mkfifo) or device entry; the entry swapped for a non-regular file between open and fstat; unusual filesystems where the no-follow open lands on a non-regular object.","commonSituations":"Pranks or probing with a FIFO .env to hang or inject into credential loading; broken sync tools materializing .env as something other than a file; container mounts that present .env as a special file.","solutions":["Inspect the entry: `ls -l .env` must start with `-`; recreate it as a regular file","If a tool created the non-regular entry, stop that tool from managing workspace .env","Regenerate .env with an editor or a plain write rather than special filesystem objects"],"exampleFix":"# before\nls -l .env        # prw-r--r-- .env   (named pipe)\n\n# after\nrm .env && printf 'KEY=value\\n' > .env\nls -l .env        # -rw-r--r-- .env","handlingStrategy":"validation","validationCode":"# .env must be a regular file\n[ -f .env ] && [ ! -L .env ] || { echo '.env missing or not a regular file'; exit 2; }\n[ \"$(stat -c '%F' .env 2>/dev/null)\" = 'regular file' ] || { echo '.env is not a regular file'; exit 2; }","typeGuard":"fn is_regular_env(path: &Path) -> bool {\n    std::fs::symlink_metadata(path)\n        .map(|m| m.is_file())\n        .unwrap_or(false)\n}","tryCatchPattern":null,"preventionTips":["Check `ls -l .env` shows a leading '-' in workspace bootstrap scripts","Never create .env as a FIFO or special file","Regenerate .env from a plain template after workspace resets"],"tags":["dotenv","security","filesystem","workspace"],"backgroundTag":"not-a-regular-file","analyzedSha":"0c42157ee52f9d55af2b506d71b46249910f77d3","analyzedAt":"2026-08-20T21:50:45.477Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}