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

  1. Run the codemod without `--max-workers 0`, or pass an explicit `--max-workers N` with N >= 1.
  2. Trace where max_workers becomes 0 (CLI flag parsing, .flowconfig, environment) and fix the value.
  3. 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

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


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)