{"record":{"id":"ceb951198d0160b1","repo":"facebook/flow","slug":"failed-to-read-stdin-ceb951","errorCode":null,"errorMessage":"failed to read stdin","messagePattern":"failed to read stdin","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"rust_port/crates/flow_cli/src/command_utils.rs","lineNumber":137,"sourceCode":"    let cwd = std::env::current_dir()\n        .expect(\"failed to get current directory\")\n        .to_string_lossy()\n        .to_string();\n    let handle_imaginary = |filename: &str| -> String {\n        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)","sourceCodeStart":119,"sourceCodeEnd":155,"githubUrl":"https://github.com/facebook/flow/blob/f88ac94bcf6992f5d5a158854d94613ebb92c6e6/rust_port/crates/flow_cli/src/command_utils.rs#L119-L155","documentation":"When the filename list is fed via stdin (--input-file -), get_filenames_from_input reads it line by line: each item of .lines() is a Result that errors when the bytes are not valid UTF-8 or on a hard I/O failure. The .expect() inside the map panics partway through collect, so one bad byte in the streamed list kills the whole command.","triggerScenarios":"Piping a filename dump containing latin-1/latin-9/cp1252 bytes (old archives, Windows exports) via `flow ... --input-file - < list.txt`; concatenating a binary file into the list; stdin backed by a failing fd or closed abnormally.","commonSituations":"Generated file lists with non-UTF-8 filenames from older filesystems; CI artifacts saved with wrong encoding; `find` output post-processed by tools that mangle bytes.","solutions":["Sanitize the list to UTF-8 before piping: `iconv -f UTF-8 -t UTF-8 -c list.txt | flow ... --input-file -`","Locate and rename (or drop) the offending non-UTF-8 filenames from the list","Generate lists with byte-safe tooling and re-encode to UTF-8 (e.g. `find ... | sed` verified with `iconv -l` round-trip)"],"exampleFix":"# before\nflow check-contents --input-file - < files.txt\n\n# after (strip invalid UTF-8 bytes first)\niconv -f UTF-8 -t UTF-8 -c files.txt | flow check-contents --input-file -","handlingStrategy":"validation","validationCode":"# Validate the list is clean UTF-8 BEFORE feeding it to the CLI:\niconv -f UTF-8 -t UTF-8 -c files.txt >/dev/null 2>&1 || \\\n  echo \"list contains invalid UTF-8\" \n\n// Rust: build the list from checked strings only\nlet raw = std::fs::read(\"files.txt\")?;\nlet text = String::from_utf8(raw)\n    .map_err(|_| \"files.txt is not valid UTF-8\")?;","typeGuard":null,"tryCatchPattern":"// In-process caller guarding against the panic:\nlet files = std::panic::catch_unwind(||\n    get_filenames_from_input(true, Some(\"-\"), None))\n    .unwrap_or_default(); // fall back to an empty list + user error","preventionTips":["Generate filename lists with UTF-8-only tooling and validate with iconv before piping","Rename non-UTF-8 filenames at the source instead of filtering at check time","Prefer a real --input-file over '-' so encoding can be validated separately"],"tags":["rust","flow-cli","stdin","utf-8","encoding","panic"],"backgroundTag":"stdin-invalid-utf8","analyzedSha":"f88ac94bcf6992f5d5a158854d94613ebb92c6e6","analyzedAt":"2026-08-20T10:41:37.992Z","schemaVersion":2},"datasetVersion":"2026-08-23T11:17:13.642Z"}