{"record":{"id":"8fe907d137f037c2","repo":"facebook/flow","slug":"check-contents-input-should-be-readable","errorCode":null,"errorMessage":"check-contents input should be readable","messagePattern":"check-contents input should be readable","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"rust_port/crates/flow_server/src/standalone.rs","lineNumber":1548,"sourceCode":"    options: &Options,\n    input: server_socket_rpc::FileInput,\n    verbose: Option<flow_common::verbose::Verbose>,\n    force: bool,\n    error_flags: cli_output::ErrorFlags,\n    strip_root: bool,\n    json: bool,\n    pretty: bool,\n    json_version: Option<flow_common_errors::error_utils::json_output::JsonVersion>,\n    offset_kind: flow_parser::offset_utils::OffsetKind,\n) -> Result<ServerResponse, CheckedDependenciesCanceled> {\n    let mut options = options.clone();\n    options.all = options.all || force;\n    options.verbose = verbose.map(Arc::new);\n    let wire_input = input.clone();\n    let input = input.into_server_file_input();\n    let content = input\n        .content_of_file_input()\n        .expect(\"check-contents input should be readable\");\n    let file_key = match &wire_input {\n        server_socket_rpc::FileInput::FileName(path)\n        | server_socket_rpc::FileInput::FileContent(Some(path), _) => {\n            FileKey::source_file_of_absolute(path)\n        }\n        server_socket_rpc::FileInput::FileContent(None, _) => FileKey::source_file_of_absolute(\"-\"),\n    };\n    let intermediate_result = flow_services_inference::type_contents::parse_contents(\n        &options,\n        env.all_unordered_libs.dupe(),\n        &content,\n        &file_key,\n    );\n    if intermediate_result.0.is_none() && intermediate_result.1.is_empty() {\n        let error_output = if json {\n            let mut buf = Vec::new();\n            flow_common_errors::error_utils::json_output::print_errors_with_offset_kind(\n                &mut buf,","sourceCodeStart":1530,"sourceCodeEnd":1566,"githubUrl":"https://github.com/facebook/flow/blob/f88ac94bcf6992f5d5a158854d94613ebb92c6e6/rust_port/crates/flow_server/src/standalone.rs#L1530-L1566","documentation":"The check-contents command handler converts the wire FileInput to a server file input and calls content_of_file_input() — the Result-returning read — but immediately expects Ok with 'check-contents input should be readable' (rust_port/crates/flow_server/src/standalone.rs:1547-1549). The Err case comes from std::fs::read_to_string on the FileInput::FileName variant: missing file, permission denied, or non-UTF-8 bytes. A recoverable I/O problem therefore crashes the server with a panic instead of returning an error response.","triggerScenarios":"Sending a check-contents request whose FileInput::FileName names a file deleted between request construction and handling, unreadable due to permissions, or containing invalid UTF-8. FileContent-based requests inline the text and never hit this path.","commonSituations":"Editor flows racing file deletion or rename; containers where the path is bind-mounted differently than the client expects; clients passing relative paths that resolve against a different server working directory.","solutions":["Send FileInput::FileContent(Some(name), Some(contents)) to inline the text and skip the server-side read","Pre-check on the client that the file exists and is readable before sending a FileName-based request","Use absolute paths the server process can resolve","Upstream: replace the expect with a ServerResponse error built from the Err(String) value"],"exampleFix":"// before\nlet content = input\n    .content_of_file_input()\n    .expect(\"check-contents input should be readable\");\n\n// after\nlet content = input\n    .content_of_file_input()\n    .map_err(|e| ServerResponse::error(format!(\"check-contents: cannot read input: {e}\")))?;","handlingStrategy":"validation","validationCode":"// Client-side pre-check before sending a FileName-based check-contents request\nmatch std::fs::read(&path) {\n    Ok(bytes) => send(FileContent(Some(path), Some(String::from_utf8_lossy(&bytes).into_owned()))),\n    Err(e) => return Err(format!(\"cannot read {path}: {e}\")),\n}","typeGuard":"fn readable_utf8(path: &str) -> bool {\n    std::fs::read(path).map(|b| std::str::from_utf8(&b).is_ok()).unwrap_or(false)\n}","tryCatchPattern":null,"preventionTips":["Prefer FileContent payloads over FileName for transient files","Send absolute paths","Handle the race gracefully: re-check existence right before the request"],"tags":["check-contents","file-io","server","panic","utf8"],"backgroundTag":"file-read-failed","analyzedSha":"f88ac94bcf6992f5d5a158854d94613ebb92c6e6","analyzedAt":"2026-08-20T10:41:37.992Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}