windmill-labs/windmill · error

WORKER_SUFFIX must only contain ASCII letters, digits and un

Error message

WORKER_SUFFIX must only contain ASCII letters, digits and underscores, got '{label}'

What it means

`create_labelled_worker_suffix` builds the per-worker name suffix from the WORKER_SUFFIX label. Windmill validates that the label consists solely of ASCII letters, digits and underscores, because it becomes part of the worker's database primary key and filesystem directory path; other characters could break naming or path handling. Any label containing spaces, dashes, dots, slashes, or non-ASCII characters triggers this error at worker startup.

Source

Thrown at backend/windmill-common/src/utils.rs:417

        None if EXIT_AFTER_N_JOBS.is_some() => create_stable_worker_suffix(hostname, index),
        None => create_default_worker_suffix(hostname),
    })
}

/// The operator's label only has to tell the worker processes of one host apart, so it is
/// appended to the stable suffix rather than replacing it: the digest is what keeps two hosts
/// whose names end on the same segment (`worker-east-1`, `worker-west-1`) from sharing an
/// identity, and it already folds in the worker index. A `-` in the label would add a segment
/// to the worker name, which [`retrieve_common_worker_prefix`] reads as the part to strip;
/// rejected rather than rewritten, since the point of the label is that two different ones
/// give two different names.
fn create_labelled_worker_suffix(
    hostname: &str,
    label: &str,
    index: usize,
) -> anyhow::Result<String> {
    if !label.chars().all(|c| c.is_ascii_alphanumeric() || c == '_') {
        return Err(anyhow::anyhow!(
            "WORKER_SUFFIX must only contain ASCII letters, digits and underscores, got '{label}'"
        ));
    }
    // The worker name is a `VARCHAR(255)` primary key and a component of the worker
    // directory's path: a label long enough to blow either only surfaces at the initial ping,
    // which the worker `expect`s.
    if label.len() > MAX_WORKER_SUFFIX_LABEL_LEN {
        return Err(anyhow::anyhow!(
            "WORKER_SUFFIX must be at most {MAX_WORKER_SUFFIX_LABEL_LEN} characters, got {}",
            label.len()
        ));
    }
    Ok(format!(
        "{}_{label}",
        create_stable_worker_suffix(hostname, index)
    ))
}

View on GitHub (pinned to e474e8803c)

Solutions

  1. Edit WORKER_SUFFIX to contain only ASCII letters, digits, and underscores (e.g. `my-worker` → `my_worker`).
  2. Remove trailing/leading whitespace or quotes picked up from the env file or shell quoting.
  3. If the label is generated from a hostname or container name, sanitize it by replacing non-alphanumeric characters with underscores before export.
  4. Restart the worker; this error is fatal at startup by design.

Example fix

// before (docker-compose env)
WORKER_SUFFIX=worker-eu-1
// after
WORKER_SUFFIX=worker_eu_1
Defensive patterns

Strategy: validation

Validate before calling

const label = process.env.WORKER_SUFFIX ?? "";
if (!/^[A-Za-z0-9_]*$/.test(label)) {
  throw new Error(`WORKER_SUFFIX '${label}' must only contain ASCII letters, digits and underscores`);
}

Type guard

function isValidWorkerSuffixLabel(label) {
  return typeof label === "string" && /^[A-Za-z0-9_]+$/.test(label);
}

Try / catch

try {
  startWorker({ suffix: process.env.WORKER_SUFFIX });
} catch (e) {
  if (String(e).includes("WORKER_SUFFIX must only contain")) {
    console.error("Sanitize WORKER_SUFFIX: replace [-. ] with _");
    process.env.WORKER_SUFFIX = process.env.WORKER_SUFFIX.replace(/[^A-Za-z0-9_]/g, "_");
    return startWorker({ suffix: process.env.WORKER_SUFFIX });
  }
  throw e;
}

Prevention

When it happens

Trigger: Starting a windmill worker with WORKER_SUFFIX set to a value containing characters outside [A-Za-z0-9_] — e.g. `WORKER_SUFFIX=my-worker`, `WORKER_SUFFIX=worker.eu`, `WORKER_SUFFIX=worker 1`, or a unicode label — when `resolve_worker_suffix` calls `create_labelled_worker_suffix`.

Common situations: Operators using hyphens (a common habit from container/host naming) in WORKER_SUFFIX; copy-pasting a hostname or docker container name (which contain dashes/dots) into WORKER_SUFFIX; templated deployments interpolating values with punctuation.

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 windmill-labs/windmill@e474e8803c (2026-09-03). Data as JSON: /api/errors/35b3ca46c50c4f22. Report an issue: GitHub.