{"record":{"id":"79d2c02c7ca9d4fa","repo":"facebook/flow","slug":"failed-to-read-input-file","errorCode":null,"errorMessage":"failed to read input file","messagePattern":"failed to read input file","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"rust_port/crates/flow_cli/src/command_utils.rs","lineNumber":142,"sourceCode":"        if allow_imaginary {\n            flow_common::files::imaginary_realpath(filename)\n        } else {\n            let msg = format!(\"File not found: {:?}\", filename);\n            flow_common_exit::exit(FlowExitStatus::NoInput, Some(&msg));\n        }\n    };\n    let input_file_filenames = match input_file {\n        Some(\"-\") => {\n            let stdin = std::io::stdin();\n            let lines: Vec<String> = stdin\n                .lock()\n                .lines()\n                .map(|l| l.expect(\"failed to read stdin\"))\n                .collect();\n            flow_common::files::canonicalize_filenames(&cwd, &handle_imaginary, &lines)\n        }\n        Some(input_file) => {\n            let content = std::fs::read_to_string(input_file).expect(\"failed to read input file\");\n            let lines: Vec<String> = content.lines().map(|l| l.to_string()).collect();\n            let file_dir = Path::new(input_file)\n                .parent()\n                .map(|p| p.to_string_lossy().to_string())\n                .unwrap_or_else(|| cwd.clone());\n            flow_common::files::canonicalize_filenames(&file_dir, &handle_imaginary, &lines)\n        }\n        None => vec![],\n    };\n    let cli_filenames = match filenames {\n        Some(filenames) => {\n            let names: Vec<String> = filenames.to_vec();\n            flow_common::files::canonicalize_filenames(&cwd, &handle_imaginary, &names)\n        }\n        None => vec![],\n    };\n    let mut result = cli_filenames;\n    result.extend(input_file_filenames);","sourceCodeStart":124,"sourceCodeEnd":160,"githubUrl":"https://github.com/facebook/flow/blob/f88ac94bcf6992f5d5a158854d94613ebb92c6e6/rust_port/crates/flow_cli/src/command_utils.rs#L124-L160","documentation":"When --input-file points at a real file, get_filenames_from_input slurps it with std::fs::read_to_string. The .expect() panics when the path does not exist (ENOENT), is not readable (EACCES), is a directory (EISDIR), or its content is not valid UTF-8. Notably this missing-file case is not routed through the friendly 'File not found' exit used elsewhere — it crashes instead.","triggerScenarios":"A typo'd or stale --input-file path (list generated in a previous CI step that was cleaned); permission-restricted file; a list saved as UTF-16 with BOM — common when generated by PowerShell `>` redirection — which read_to_string rejects as invalid UTF-8.","commonSituations":"PowerShell/Windows-generated file lists (UTF-16LE); cron jobs using relative paths from a different cwd; artifacts deleted between pipeline stages; files with exotic encodings.","solutions":["Verify the path and permissions before running: `test -r list.txt && flow ... --input-file list.txt`","Re-encode the file to UTF-8: `iconv -f UTF-16 -t UTF-8 list.txt > list.utf8.txt`, or in PowerShell use `Out-File -Encoding utf8`","Use absolute paths for --input-file in cron/CI so cwd changes cannot break resolution"],"exampleFix":"# before (PowerShell wrote UTF-16 with BOM)\nflow check-contents --input-file files.txt\n\n# after\niconv -f UTF-16 -t UTF-8 files.txt > files.utf8.txt\nflow check-contents --input-file files.utf8.txt","handlingStrategy":"validation","validationCode":"// Validate existence, readability, and UTF-8 before passing --input-file:\nlet p = std::path::Path::new(list);\nlet bytes = std::fs::read(p).unwrap_or_else(|e| {\n    eprintln!(\"cannot read {p:?}: {e}\");\n    std::process::exit(1);\n});\nif std::str::from_utf8(&bytes).is_err() {\n    eprintln!(\"{p:?} is not UTF-8 (PowerShell `>` writes UTF-16)\");\n    std::process::exit(1);\n}","typeGuard":null,"tryCatchPattern":"let content = match std::fs::read_to_string(input_file) {\n    Ok(c) => c,\n    Err(e) => flow_common_exit::exit(FlowExitStatus::InputError,\n        Some(&format!(\"cannot read input file {input_file:?}: {e}\"))),\n};","preventionTips":["Always `test -r <list>` in scripts before invoking with --input-file","Generate lists as UTF-8 (PowerShell: Out-File -Encoding utf8; never bare `>`)","Use absolute paths for --input-file in cron/CI to survive cwd changes"],"tags":["rust","flow-cli","filesystem","utf-8","file-not-found","panic"],"backgroundTag":"file-not-found","analyzedSha":"f88ac94bcf6992f5d5a158854d94613ebb92c6e6","analyzedAt":"2026-08-20T10:41:37.992Z","schemaVersion":2},"datasetVersion":"2026-08-23T11:17:13.642Z"}