windmill-labs/windmill · error

EXIT_AFTER_N_JOBS must be a positive integer (or 0 to disabl

Error message

EXIT_AFTER_N_JOBS must be a positive integer (or 0 to disable), got '{v}'

What it means

`validate_worker_lifecycle_env` checks the EXIT_AFTER_N_JOBS environment variable at worker startup. If the variable is set but not parseable as a u64 (empty string counts as unset here and is fine), the worker refuses to start. Fail-fast is deliberate: silently ignoring an unparseable value would leave a worker that was supposed to recycle after N jobs running forever, defeating the deployment's restart guarantee.

Source

Thrown at backend/windmill-common/src/worker.rs:498

    .and_then(|x| x.parse::<bool>().ok())
    .unwrap_or(false);

    // Features flags:
    pub static ref DISABLE_FLOW_SCRIPT: bool = std::env::var("DISABLE_FLOW_SCRIPT").ok().is_some_and(|x| x == "1" || x == "true");

    pub static ref ROOT_STANDALONE_BUNDLE_DIR: String = format!("{}/.windmill/standalone_bundle", std::env::var("HOME").unwrap_or_else(|_| "/root".to_string()));
}

lazy_static::lazy_static! {
    pub static ref ROOT_CACHE_NOMOUNT_DIR: String = format!("{}/cache_nomount/", *WINDMILL_DIR);
}

/// Refuses to start on an `EXIT_AFTER_N_JOBS` that does not parse. Silently ignoring it
/// would leave a worker meant to recycle its environment running forever without doing so,
/// which is exactly the guarantee the deployment set it for.
pub fn validate_worker_lifecycle_env() -> anyhow::Result<()> {
    match std::env::var("EXIT_AFTER_N_JOBS") {
        Ok(v) if !v.is_empty() && v.parse::<u64>().is_err() => Err(anyhow::anyhow!(
            "EXIT_AFTER_N_JOBS must be a positive integer (or 0 to disable), got '{v}'"
        )),
        _ => Ok(()),
    }
}

/// Whether native mode is forced by the environment (NATIVE_MODE=true env var or WORKER_GROUP=native).
/// This does NOT account for native_mode set in the DB worker group config — for that, read
/// `WORKER_CONFIG.native_mode` which combines all sources.
pub fn is_native_mode_from_env() -> bool {
    *NATIVE_MODE || *WORKER_GROUP == "native"
}

/// True iff this process is configured to act as the production cloud cluster:
/// `CLOUD_HOSTED=true` AND `BASE_URL`'s host matches `CLOUD_PRODUCTION_HOST`.
/// Centralized so the API setter, the runtime pull path, and any future cloud-
/// only feature share one canonical check (rather than re-implementing the
/// scheme/host parser at each call site).

View on GitHub (pinned to e474e8803c)

Solutions

  1. Set EXIT_AFTER_N_JOBS to a plain non-negative integer, e.g. `EXIT_AFTER_N_JOBS=100` (0 disables the exit-after-N behavior).
  2. Remove surrounding whitespace/quotes from the value in your env file or manifest.
  3. Check for templating artifacts: rendered values like `100.0` or `nil` must be corrected to integers.
  4. Unset the variable entirely if you do not want lifecycle-based recycling.

Example fix

// before (values.yaml env)
- name: EXIT_AFTER_N_JOBS
  value: "50.0"
// after
- name: EXIT_AFTER_N_JOBS
  value: "50"
Defensive patterns

Strategy: validation

Validate before calling

const raw = process.env.EXIT_AFTER_N_JOBS;
if (raw !== undefined && raw !== "" && !/^\d+$/.test(raw)) {
  throw new Error(`EXIT_AFTER_N_JOBS must be a non-negative integer, got '${raw}'`);
}

Try / catch

try {
  startWorker();
} catch (e) {
  if (String(e).includes("EXIT_AFTER_N_JOBS")) {
    console.error(`Fix EXIT_AFTER_N_JOBS: '${process.env.EXIT_AFTER_N_JOBS}' is not an integer. Use e.g. 100, or 0/unset to disable.`);
    process.exit(1);
  }
  throw e;
}

Prevention

When it happens

Trigger: Setting `EXIT_AFTER_N_JOBS=ten`, `EXIT_AFTER_N_JOBS=5.0`, `EXIT_AFTER_N_JOBS=" 10"`, `EXIT_AFTER_N_JOBS=-3` (negative), or any non-integer value, then starting a worker — `windmill_main` calls the validator and aborts on error.

Common situations: Using a float or unit-suffixed value ('50 jobs'); negative numbers assumed valid; shell quoting leaving stray spaces; Helm/k8s templates rendering numbers as strings with formatting; YAML `EXIT_AFTER_N_JOBS: 010` confusion is fine but `" "` whitespace-only strings fail parse.

Related errors


AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03). Data as JSON: /api/errors/c5c229c76232d3e1. Report an issue: GitHub.