{"record":{"id":"9c7fdd8e8a8c66ad","repo":"affaan-m/ECC","slug":"label-must-be-a-regular-file","errorCode":null,"errorMessage":"{label} must be a regular file","messagePattern":"(.+?) must be a regular file","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"ecc2/src/main.rs","lineNumber":1409,"sourceCode":"    details: BTreeMap<String, String>,\n}\n\nfn read_bounded_file(path: &Path, max_bytes: u64, label: &str) -> Result<Vec<u8>> {\n    let mut options = File::options();\n    options.read(true);\n    #[cfg(unix)]\n    {\n        use std::os::unix::fs::OpenOptionsExt;\n        options.custom_flags(libc::O_NONBLOCK);\n    }\n    let file = options\n        .open(path)\n        .with_context(|| format!(\"Failed to open {}\", path.display()))?;\n    let metadata = file\n        .metadata()\n        .with_context(|| format!(\"Failed to inspect {}\", path.display()))?;\n    if !metadata.is_file() {\n        anyhow::bail!(\"{label} must be a regular file\");\n    }\n\n    let read_limit = max_bytes\n        .checked_add(1)\n        .context(\"bounded input byte limit is too large\")?;\n    let mut content = Vec::new();\n    file.take(read_limit)\n        .read_to_end(&mut content)\n        .with_context(|| format!(\"Failed to read {}\", path.display()))?;\n    if content.len() as u64 > max_bytes {\n        anyhow::bail!(\"{label} exceeds the {max_bytes}-byte limit\");\n    }\n    Ok(content)\n}\n\n#[tokio::main]\nasync fn main() -> Result<()> {\n    tracing_subscriber::fmt()","sourceCodeStart":1391,"sourceCodeEnd":1427,"githubUrl":"https://github.com/affaan-m/ECC/blob/01e15490f04e29cfefe3896951f43db46994d8ee/ecc2/src/main.rs#L1391-L1427","documentation":"Runtime error from a bounded-file reader in ecc2/src/main.rs. After opening `path` (with O_NONBLOCK on unix) and reading metadata, the code checks metadata.is_file(); if the path is not a regular file it bails with \"{label} must be a regular file\", where `label` names the input (e.g. a flag like --patch or --input). The check excludes directories, devices, sockets, pipes, and non-regular specials, so the input cannot be streamed or stat'd as bytes.","triggerScenarios":"Passing a path to a bounded-input flag where the path resolves to a directory, FIFO, device, socket, or symlink whose target is not a regular file. The open succeeds but metadata().is_file() returns false.","commonSituations":"User passed a directory path by mistake; a symlink points at a directory; /dev/null or /dev/stdin used where a regular file is required; a named pipe created by another process; a glob expanded to a directory.","solutions":["Point the flag at an actual file path; verify with ls -l / stat.","If you intended stdin, check whether the command supports - as a sentinel; otherwise write to a temp file first.","Resolve symlinks (readlink -f) to confirm the target is a regular file.","Avoid passing device nodes or pipes to flags that require regular files."],"exampleFix":"# before\n$ ecc cmd --patch ./patches/\n\n# after\n$ ecc cmd --patch ./patches/0001-fix.patch","handlingStrategy":"validation","validationCode":"// Verify regular-file-ness before invoking the bounded reader.\nuse std::fs;\nfn assert_regular_file(label: &str, path: &Path) -> Result<()> {\n    let meta = fs::symlink_metadata(path)?;\n    if meta.file_type().is_symlink() {\n        let target = fs::metadata(path)?;\n        anyhow::ensure!(target.is_file(), \"{label} must be a regular file\");\n    } else {\n        anyhow::ensure!(meta.is_file(), \"{label} must be a regular file\");\n    }\n    Ok(())\n}","typeGuard":"fn is_regular_file(path: &Path) -> bool {\n    fs::metadata(path).map(|m| m.is_file()).unwrap_or(false)\n}","tryCatchPattern":"let content = read_bounded(label, path, max_bytes).map_err(|e| {\n    if e.to_string().contains(\"must be a regular file\") {\n        anyhow::anyhow!(\"{e}; pass a file path, not a directory or device\")\n    } else {\n        e\n    }\n})?;","preventionTips":["Pre-check paths with fs::metadata before passing to bounded readers.","Resolve symlinks (fs::canonicalize) and re-check before use.","Avoid device nodes and named pipes for inputs that must be regular files.","Validate at the CLI parser with value parsers when possible."],"tags":["rust","filesystem","validation","cli"],"backgroundTag":null,"analyzedSha":"01e15490f04e29cfefe3896951f43db46994d8ee","analyzedAt":"2026-08-13T00:31:08.655Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}