facebook/flow · error
Replacement_printer: Input file, "{}", couldn't be read.
Error message
Replacement_printer: Input file, "{}", couldn't be read. What it means
The replacement printer produces codemod output by reading the original file and applying an AST-diff patch to its text. with_content_of_file_input() calls content_of_file_input(); if that read returns Err — missing file, permission denied, path is a directory — the function panics with the filename, because computing replacements without the source content is impossible.
Source
Thrown at rust_port/crates/flow_parser_utils_output/src/replacement_printer.rs:42
list_utils::to_string(
"",
|(s, e, p): &(usize, usize, String)| {
format!("Start: <{}> End: <{}> Patch: <{}>\n", s, e, p)
},
p,
)
}
fn with_content_of_file_input<T>(file: &FileInput, f: impl FnOnce(&str) -> T) -> T {
match file.content_of_file_input() {
Ok(contents) => f(&contents),
Err(_) => {
let file_name = file.filename_of_file_input();
let error_msg = format!(
"Replacement_printer: Input file, \"{}\", couldn't be read.",
file_name
);
panic!("{}", error_msg)
}
}
}
pub fn mk_loc_patch_ast_differ(opts: &Opts, diff: &NodeChanges) -> LocPatch {
ast_diff_printer::edits_of_changes(opts, diff)
}
pub fn mk_patch_ast_differ(opts: &Opts, diff: &NodeChanges, content: &str) -> Patch {
let offset_table = OffsetTable::make(content);
let offset = |pos: Position| -> usize { offset_table.offset(pos).unwrap() as usize };
mk_loc_patch_ast_differ(opts, diff)
.into_iter()
.map(|(loc, text)| (offset(loc.start), offset(loc.end), text))
.collect()
}
pub fn mk_patch_ast_differ_unsafe(opts: &Opts, diff: &NodeChanges, file: &FileInput) -> Patch {View on GitHub (pinned to f88ac94bcf)
Solutions
- Verify the filename from the panic message: test -r <file>; fix the input path if it is wrong.
- Re-run on a clean checkout with concurrent tooling stopped (stash, close the editor, stop watchers).
- When batching codemods, run them sequentially and re-stat each input right before the printing step, skipping deleted files.
- Patch with_content_of_file_input to return an error or skip-with-warning instead of panicking, if you control the fork.
Example fix
// before
with_content_of_file_input(&file, |content| print_patches(content));
// after: guard, then print
if file.content_of_file_input().is_err() {
eprintln!("skipping unreadable input: {}", file.filename_of_file_input());
return Ok(());
}
with_content_of_file_input(&file, |content| print_patches(content)); Defensive patterns
Strategy: validation
Validate before calling
use std::io::Read;
fn file_readable(path: &str) -> bool {
std::fs::File::open(path)
.and_then(|mut f| { let mut b = [0u8; 1]; f.read(&mut b).map(|_| ()) })
.is_ok()
}
// skip inputs that would panic the replacement printer
if !file_readable(input_path) { continue; } Try / catch
let out = std::panic::catch_unwind(|| with_content_of_file_input(&file, print_fn));
if out.is_err() {
eprintln!("skipping unreadable input: {}", file.filename_of_file_input());
continue; // codemod continues with remaining files
} Prevention
- Run codemods on a clean checkout with editors, watchers, and formatters stopped.
- Re-stat each input file right before printing; skip anything that vanished since discovery.
- Run batched codemods sequentially so one never deletes another's input.
- Resolve --input paths to absolute paths once at CLI parse time.
When it happens
Trigger: Running a codemod/transform that routes through the replacement printer when the FileInput path no longer exists or is unreadable at print time: the file was deleted after discovery (another codemod in the same batch, a concurrent git operation), the path is wrong, or permissions deny the read.
Common situations: Codemods run while editors/watchers rewrite files; batched codemods where an earlier one deletes inputs of a later one; sandboxes without read access; --input arguments that are directories or have typos; files swapped by a rebase between diffing and printing.
Understand the failure class
Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.
Related errors
- workers required for init
- recheck failed
- check-contents input should be readable
- ${message}
- import/export cannot be inserted into a ${insertionParent.pa
AI-assisted analysis of facebook/flow@f88ac94bcf (2026-08-20).
Data as JSON: /api/errors/925c7a6e3639cf34.
Report an issue: GitHub.