{"record":{"id":"b8049bb0e32b4c61","repo":"facebook/flow","slug":"ensure-parsed-or-trigger-recheck-failed","errorCode":null,"errorMessage":"ensure_parsed_or_trigger_recheck failed","messagePattern":"ensure_parsed_or_trigger_recheck failed","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"rust_port/crates/flow_codemods/src/utils/codemod_runner.rs","lineNumber":728,"sourceCode":"    {\n        let _should_print = _options.profile;\n        let reader = _transaction.clone();\n        let get_dependent_files = |_: &flow_common_utils::graph::Graph<FileKey>,\n                                   _: &flow_common_utils::graph::Graph<FileKey>,\n                                   _: &BTreeSet<FileKey>|\n         -> std::pin::Pin<\n            Box<dyn std::future::Future<Output = BTreeSet<FileKey>>>,\n        > { Box::pin(async { BTreeSet::new() }) };\n        let (_dependency_info, _components, files_to_merge, _) =\n            merge_targets(_env, _options, &(), get_dependent_files, &_roots).await;\n        if let Some(pool) = _workers {\n            flow_services_inference::type_service::ensure_parsed_or_trigger_recheck(\n                pool,\n                &reader,\n                &Arc::new(_options.clone()),\n                files_to_merge.clone().into_iter().collect(),\n            )\n            .expect(\"ensure_parsed_or_trigger_recheck failed\");\n        }\n        let mutator = ();\n        flow_hh_logger::info!(\"Merging {} files\", files_to_merge.len());\n        if let Some(pool) = _workers {\n            let _merge_results = flow_services_inference::merge_service::merge_runner(\n                pool,\n                &reader,\n                _options,\n                false, // for_find_all_refs\n                _dependency_info.sig_dependency_graph(),\n                _components,\n                &files_to_merge,\n                move |_transaction: &flow_heap::parsing_heaps::Transaction,\n                      _opts: &Options,\n                      _for_find_all_refs: bool,\n                      _component: vec1::Vec1<FileKey>| {\n                    Ok(merge_job(\n                        &mutator,","sourceCodeStart":710,"sourceCodeEnd":746,"githubUrl":"https://github.com/facebook/flow/blob/f88ac94bcf6992f5d5a158854d94613ebb92c6e6/rust_port/crates/flow_codemods/src/utils/codemod_runner.rs#L710-L746","documentation":"In the codemod runner's first merge pass, `flow_services_inference::type_service::ensure_parsed_or_trigger_recheck` parses the merge set and verifies nothing changed on disk since the run began. It returns `Err(RecheckError::Canceled(files))` when files were modified concurrently (\"unexpected file changes\"), and this expect converts that cancellation into a panic.","triggerScenarios":"An editor autosave, format-on-save, git checkout/pull/rebase, another flow process, or a second codemod rewrites one of the files between the codemod's initial parse and this merge step; watchman-style daemons touching the repo during a long run.","commonSituations":"Running codemods with the IDE open and autosave enabled; concurrent `flow server`/daemon on the same root; scripts that `git pull` while codemods run; two codemods launched in parallel.","solutions":["Re-run the codemod — a one-off concurrent edit during the run is the usual cause.","Quiesce other writers first: `flow stop`, close or pause the editor's autosave, finish git operations before starting.","Never run two codemods (or a codemod plus a flow server) on the same root at once.","If it persists, find the process rewriting files (inotify/audit tools) and pause it for the duration."],"exampleFix":"// before\nflow_services_inference::type_service::ensure_parsed_or_trigger_recheck(\n    pool, &reader, &Arc::new(_options.clone()), files,\n).expect(\"ensure_parsed_or_trigger_recheck failed\");\n\n// after\nmatch flow_services_inference::type_service::ensure_parsed_or_trigger_recheck(\n    pool, &reader, &Arc::new(_options.clone()), files,\n) {\n    Ok(()) => {}\n    Err(flow_services_inference::type_service::RecheckError::Canceled(files)) => {\n        eprintln!(\"{} files changed during the codemod run; re-run on a quiesced repo\", files.len());\n        std::process::exit(2);\n    }\n    Err(other) => panic!(\"ensure_parsed_or_trigger_recheck failed: {other:?}\"),\n}","handlingStrategy":"retry","validationCode":"// Cheap staleness probe: mtimes must not change across a short interval before the run\nfn files_look_stable(files: &[std::path::PathBuf]) -> bool {\n    let snap = |fs: &[std::path::PathBuf]| fs.iter()\n        .map(|p| p.metadata().ok().and_then(|m| m.modified().ok()))\n        .collect::<Vec<_>>();\n    let a = snap(files);\n    std::thread::sleep(std::time::Duration::from_millis(500));\n    a == snap(files)\n}","typeGuard":null,"tryCatchPattern":"match ensure_parsed_or_trigger_recheck(pool, &reader, &options, files) {\n    Ok(()) => {}\n    Err(RecheckError::Canceled(files)) => {\n        // files changed mid-run: safe to re-run the codemod from scratch once the repo is quiet\n        eprintln!(\"{} files changed during the run; retrying\", files.len());\n    }\n    Err(other) => panic!(\"{other:?}\"),\n}","preventionTips":["Quiesce the repository during codemods: stop the flow server, disable autosave/format-on-save, finish git operations.","Run only one codemod per repository root at a time (use flock if scripts may race).","Commit or branch before running so interrupted runs can be re-run safely."],"tags":["codemod","concurrent-modification","recheck","parse"],"backgroundTag":"concurrent-file-modification","analyzedSha":"f88ac94bcf6992f5d5a158854d94613ebb92c6e6","analyzedAt":"2026-08-20T10:41:37.992Z","schemaVersion":2},"datasetVersion":"2026-08-23T06:17:17.905Z"}