facebook/flow · error
workers required for init
Error message
workers required for init
What it means
During codemod initialization the runner does `workers.as_ref().expect("workers required for init")`. `Genv.workers` is built by `make_genv`, which creates a thread pool only when `options.max_workers > 0` and sets `None` when `max_workers == 0`. Typed codemod runners need that pool for `init_from_scratch`, so a zero-worker configuration panics here.
Solutions
- Run the codemod without `--max-workers 0`, or pass an explicit `--max-workers N` with N >= 1.
- Trace where max_workers becomes 0 (CLI flag parsing, .flowconfig, environment) and fix the value.
- If constructing the environment in code, use `make_genv` with max_workers >= 1 so a pool is created.
Example fix
// before
let pool = workers.as_ref().expect("workers required for init");
// after
let Some(pool) = workers.as_ref() else {
eprintln!("codemod requires at least one worker (max_workers is 0); pass --max-workers >= 1");
std::process::exit(2);
}; Defensive patterns
Strategy: validation
Validate before calling
// Before launching the codemod, reject a zero worker configuration
if options.max_workers < 1 {
eprintln!("codemod requires max_workers >= 1 (got {})", options.max_workers);
std::process::exit(2);
} Try / catch
let Some(pool) = workers.as_ref() else {
eprintln!("max_workers is 0; pass --max-workers >= 1");
std::process::exit(2);
}; Prevention
- Never pass --max-workers 0 to codemod binaries; omit the flag to use the default pool.
- Validate max_workers at configuration load time, not deep in the runner.
- When embedding the runner, build Genv via make_genv with max_workers >= 1.
When it happens
Trigger: Launching the codemod binary with `--max-workers 0` (or a config/env override that zeroes max_workers); building a Genv manually with max_workers=0 and then running a runner that requires a pool.
Common situations: Users passing `--max-workers 0` intending single-threaded execution; flag values copied from other tools where 0 means auto; tests embedding the runner with a minimal Genv.
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.
Related errors
- workers required for recheck
- $FLOW_STACK_SIZE must be a number, got
- max_workers should be positive
- Attempted to insert a statement into
- Cannot perform a remove mutation on node of type
AI-assisted analysis of facebook/flow@21c11b2ead (2026-08-20).
Data as JSON: /api/errors/4fd96d1e82c4685d.
Report an issue: GitHub.
Appendix: source
Thrown at rust_port/crates/flow_codemods/src/utils/codemod_runner.rs:1197
}
flow_services_inference::merge_service::CheckJobOutcome::PerFileError(e) => {
acc.insert(file, Err(e));
}
flow_services_inference::merge_service::CheckJobOutcome::Canceled(c) => {
return Err(c);
}
}
}
acc
};
flow_hh_logger::info!("Pre-checking Done");
flow_hh_logger::info!("Storing pre-checking results");
C::store_precheck_result(precheck_result);
flow_hh_logger::info!("Storing pre-checking results Done");
flow_hh_logger::info!("Checking+Codemodding {} files", _roots.len());
let options = C::check_options(_options.clone());
let metadata =
flow_typing_context::mk_context_metadata(&options, _env.master_cx.global_libdefs());
let visit_fn: &(
dyn Fn(
&Options,
&ast::Program<Loc, Loc>,
codemod_context::typed::TypedCodemodContext<'_>,
) -> Self::Accumulator
+ Sync
) = &C::visit;
let (mut inner, cache) = flow_services_inference::merge_service::mk_check(
reader.clone(),
Arc::new(options.clone()),
_env.configured_libs(),
&_env.master_cx,
flow_services_references::find_refs_types::empty_request(),
);
let mut check_fn = |file: FileKey| {
post_check(
visit_fn,View on GitHub (pinned to 21c11b2ead)