facebook/flow · error

recheck failed

Error message

recheck failed

What it means

The codemod's incremental recheck calls `type_service::recheck`, which returns `Err(RecheckError)` with variants `TooSlow` and `Canceled(files)`. Here it is invoked with `changed_mergebase: None`, and per the code comment TooSlim/TooSlow requires `changed_mergebase=Some(true)`, so a failure at this expect means `Canceled`: files changed unexpectedly on disk while the recheck was running.

Source

Thrown at rust_port/crates/flow_codemods/src/utils/codemod_runner.rs:1255

            _roots.iter().cloned().collect();
        updates.add(Some(focused_set), None, None);
        let find_ref_request = flow_services_references::find_refs_types::empty_request();
        let files_to_force = flow_common_utils::checked_set::CheckedSet::empty();
        let mut will_be_checked_files = flow_common_utils::checked_set::CheckedSet::empty();
        let recheck_result = flow_services_inference::type_service::recheck(
            pool,
            &_genv.committed_heap,
            &options_arc,
            &updates,
            &find_ref_request,
            files_to_force,
            false,
            None,  // changed_mergebase
            false, // missed_changes
            &mut will_be_checked_files,
            Arc::new(env),
        );
        let (_, _, _, prepared) = recheck_result.expect("recheck failed");
        let env = prepared.commit();
        let transaction = ActiveTransaction::new(_genv.committed_heap.clone());
        log_input_files(&_roots);
        let results = TRC::merge_and_check(
            &env,
            workers,
            options,
            &profiling,
            _roots,
            _iteration,
            &transaction.handle(),
        )
        .await?;
        let env = EnvTransaction::new(env).into_env();
        Ok(((), (env, results)))
    }

    #[allow(unreachable_code)]

View on GitHub (pinned to f88ac94bcf)

Solutions

  1. Re-run the codemod on a quiesced repository — a transient concurrent edit is the normal cause.
  2. Stop concurrent writers: `flow stop`, disable autosave/format-on-save, finish git operations first.
  3. Serialize codemods per repository root.
  4. For very large codemods, split into batches to shrink the window in which edits cancel the recheck.

Example fix

// before
let (_, _, _, prepared) = recheck_result.expect("recheck failed");

// after
let (_, _, _, prepared) = match recheck_result {
    Ok(r) => r,
    Err(flow_services_inference::type_service::RecheckError::Canceled(files)) => {
        eprintln!("{} files changed during recheck; re-run the codemod on a quiet repo", files.len());
        std::process::exit(2);
    }
    Err(other) => panic!("recheck failed: {other:?}"),
};
Defensive patterns

Strategy: retry

Validate before calling

// Reduce the race window: confirm roots are quiet immediately before recheck
fn roots_quiet(roots: &BTreeSet<FileKey>) -> bool {
    let m = |f: &FileKey| std::fs::metadata(f.to_absolute()).ok().and_then(|x| x.modified().ok());
    let a: Vec<_> = roots.iter().map(m).collect();
    std::thread::sleep(std::time::Duration::from_millis(300));
    roots.iter().map(m).eq(a.into_iter())
}

Try / catch

let (_, _, _, prepared) = match recheck_result {
    Ok(r) => r,
    Err(RecheckError::Canceled(files)) => {
        eprintln!("{} files changed during recheck; re-run the codemod", files.len());
        std::process::exit(2);
    }
    Err(other) => panic!("recheck failed: {other:?}"),
};

Prevention

When it happens

Trigger: Autosave, formatter, git checkout, or another flow process rewrites files while the codemod is in its recheck/merge-check phase; long runs make the race window larger.

Common situations: IDE open with autosave during a long codemod; concurrent daemons (watchman, flow server, second codemod) on the same root; scripts mutating the repo in parallel with the codemod.

Related errors


AI-assisted analysis of facebook/flow@f88ac94bcf (2026-08-20). Data as JSON: /api/errors/6c3922ce831e92a8. Report an issue: GitHub.