{"record":{"id":"41f29e17e1a51078","repo":"facebook/flow","slug":"failed-to-read-stdin","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/ast_command.rs","lineNumber":145,"sourceCode":"    let spec = command_utils::add_offset_style_flag(spec);\n    let spec = command_utils::add_from_flag(spec);\n    let spec = command_utils::add_path_flag(spec);\n    spec.anon(\"file\", &arg_spec::optional(arg_spec::string()))\n}\n\nenum AstResultType {\n    AstJson(flow_parser::ast::expression::Expression<flow_parser::loc::Loc, flow_parser::loc::Loc>),\n    AstJs(flow_parser::ast::Program<flow_parser::loc::Loc, flow_parser::loc::Loc>),\n}\n\nfn get_file(path: Option<String>, filename: Option<String>) -> FileInput {\n    match filename {\n        Some(filename) => FileInput::FileName(command_utils::expand_path(&filename)),\n        None => {\n            let mut content = String::new();\n            std::io::stdin()\n                .read_to_string(&mut content)\n                .expect(\"failed to read stdin\");\n            FileInput::FileContent(path, content.into())\n        }\n    }\n}\n\nfn offset(\n    offset_table: &flow_parser::offset_utils::OffsetTable,\n    position: flow_parser::loc::Position,\n) -> usize {\n    offset_table.offset(position).unwrap() as usize\n}\n\nfn translate_token(\n    offset_table: &flow_parser::offset_utils::OffsetTable,\n    token: &flow_parser::TokenSinkResult,\n) -> serde_json::Value {\n    let context = match token.token_context {\n        flow_parser::LexMode::Normal => \"normal\",","sourceCodeStart":127,"sourceCodeEnd":163,"githubUrl":"https://github.com/facebook/flow/blob/f88ac94bcf6992f5d5a158854d94613ebb92c6e6/rust_port/crates/flow_cli/src/ast_command.rs#L127-L163","documentation":"When `flow ast` is invoked without a filename it reads the whole document from stdin via stdin().read_to_string and calls .expect(\"failed to read stdin\") on the result — so any read error panics the CLI rather than printing a graceful message. The dominant cause is invalid UTF-8: read_to_string decodes into a String and fails on non-UTF-8 bytes (binary or legacy-encoded input). A closed/broken stdin pipe produces the same panic.","triggerScenarios":"Piping a file with non-UTF-8 bytes into `flow ast` (cat legacy.js | flow ast with no filename flag), piping a binary file picked by a glob, or running the command with stdin closed or redirected from a dead fd.","commonSituations":"Latin-1/Windows-1252 encoded sources; minified third-party bundles with stray bytes; CI invoking the command with no stdin attached; an upstream producer crashing mid-pipe so the read end errors.","solutions":["Pass a filename argument instead of stdin when the input may not be UTF-8 clean — the file path branch does not do the stdin decode.","Convert the input first: iconv -t UTF-8 file.js | flow ast.","Check what is actually being piped (file / xxd) — a binary file in the glob is usually the surprise."],"exampleFix":"# before: non-UTF-8 bytes panic with 'failed to read stdin'\ncat legacy.js | flow ast\n\n# after: convert encoding first, or point at a file\niconv -t UTF-8 legacy.js | flow ast\nflow ast --filename legacy-utf8.js","handlingStrategy":"validation","validationCode":"# Validate the payload is UTF-8 before piping it to `flow ast`.\niconv -t UTF-8 input.js >/dev/null 2>&1 || echo \"input is not UTF-8\"\n# or: file -bi input.js  -> charset must be utf-8/us-ascii","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Normalize all source files to UTF-8 in the repo (add an encoding lint).","Prefer passing a filename argument over stdin when input provenance is unknown.","In scripts, check encodings with `file` before piping into Flow CLI commands."],"tags":["cli","stdin","utf-8","panic","rust"],"backgroundTag":"invalid-utf8-input","analyzedSha":"f88ac94bcf6992f5d5a158854d94613ebb92c6e6","analyzedAt":"2026-08-20T10:41:37.992Z","schemaVersion":2},"datasetVersion":"2026-08-23T11:17:13.642Z"}