{"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":"validation","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/8321021c54d670126ce3b2969d5deb880b4b0c2a/ecc2/src/main.rs#L1391-L1427","documentation":"A bounded-file-reading helper in the CLI opens a user-supplied path and verifies via `File::metadata()` that it is a regular file before reading. Directories, FIFOs, device nodes, and other special files are rejected so reads are size-bounded and deterministic. The error message uses the caller-provided `label` to identify which input failed.","triggerScenarios":"Passing a directory path, a named pipe, /dev/null-style device file, or a symlink resolving to a non-regular file to the bounded input reader (e.g. a CLI flag pointing at a directory).","commonSituations":"Typo'd CLI argument where a directory was given instead of a file, piping setups where the path is a FIFO, or platform-specific special files being used as input.","solutions":["Point the argument at an actual regular file, not a directory or special file.","Verify the path exists and is a file with `ls -l` / `file <path>` before invoking.","If reading a directory was intended, enumerate its files and pass individual file paths instead."],"exampleFix":"// before\nlet content = read_bounded_file(path, \"plan\", max_bytes)?;\n// after\nlet meta = std::fs::metadata(path)?;\nanyhow::ensure!(meta.is_file(), \"expected a file, got: {}\", path.display());\nlet content = read_bounded_file(path, \"plan\", max_bytes)?;","handlingStrategy":"validation","validationCode":"let meta = std::fs::metadata(path)\n    .with_context(|| format!(\"cannot access {}\", path.display()))?;\nanyhow::ensure!(meta.is_file(), \"{} is not a regular file\", path.display());","typeGuard":"fn is_regular_file(p: &std::path::Path) -> bool {\n    std::fs::metadata(p).map(|m| m.is_file()).unwrap_or(false)\n}","tryCatchPattern":"match read_bounded_file(path, label, max_bytes) {\n    Ok(content) => content,\n    Err(e) if e.to_string().contains(\"must be a regular file\") => {\n        eprintln!(\"{}: pass a regular file path, not a directory/special file\", path.display());\n        std::process::exit(2);\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Use shell/tab completion so directory arguments are not mistyped","Pre-flight check paths with `file <path>` in scripts","Symlink-following metadata is used, so verify final target is a file"],"tags":["filesystem","cli","input-validation"],"backgroundTag":"incompatible-source-type","analyzedSha":"8321021c54d670126ce3b2969d5deb880b4b0c2a","analyzedAt":"2026-09-16T10:08:13.343Z","contentChangedAt":"2026-09-16T10:08:13.343Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}