apache/beam · error · IllegalArgumentException

Unknown delay type

Error message

Unknown delay type %s

What it means

SyntheticDelay.delay applies a per-record or batch delay of a configured type (SLEEP to idle the thread, or CPU-busy work) for Beam's synthetic sources used in load testing. If the configured delay type doesn't match any supported enum case, the default branch throws IllegalArgumentException naming the type.

Solutions

  1. Correct the delay type in your options to a supported value (e.g., SLEEP) as defined by SyntheticOptions.DelayType in your Beam version.
  2. Check for case-sensitivity/typo issues in the JSON options file driving the synthetic source.
  3. If constructing options programmatically, use the DelayType enum constants instead of raw strings.

Example fix

// before (options JSON)
{"delayType": "THREAD_WAIT", "avgDelayMillis": 10}
// after
{"delayType": "SLEEP", "avgDelayMillis": 10}
Defensive patterns

Strategy: validation

Validate before calling

// Java — verify delay type before building options
String t = opts.get("delayType").asText();
if (!t.equals("SLEEP") && !t.equals("NONE")) { // check against your Beam version's DelayType values
  throw new IllegalArgumentException("Unsupported delayType: " + t);
}

Try / catch

try {
  long ms = SyntheticDelay.delay(base, sigma, delayType, rnd);
} catch (IllegalArgumentException e) {
  // unknown delay type: correct the DelayType in synthetic options
}

Prevention

When it happens

Trigger: Configuring synthetic source options with an unknown 'delayType' (e.g., in the load-test pipeline's --runnerOptions/synthetic JSON) and processing a record; the static delay(...) is also recursively called for average/sigma delays, so any nested call with an invalid type triggers it.

Common situations: Typos in load-test pipeline options ('slep' vs 'sleep'), options copied from different Beam versions with different enum sets, or programmatic construction of SyntheticOptions.DelayType with a stale value.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


AI-assisted analysis of apache/beam@12126d8942 (2026-09-13). Data as JSON: /api/errors/e3cb5a245d8b19a2. Report an issue: GitHub.

Appendix: source

Thrown at sdks/java/io/synthetic/src/main/java/org/apache/beam/sdk/io/synthetic/delay/SyntheticDelay.java:72

      case SLEEP:
        Uninterruptibles.sleepUninterruptibly(
            Math.max(0L, delay.getMillis()), TimeUnit.MILLISECONDS);
        return delay.getMillis();
      case MIXED:
        // Mixed mode: for each millisecond of delay randomly choose to spin or sleep.
        // This is enforced at millisecond granularity since that is the minimum duration that
        // Thread.sleep() can sleep. Millisecond is also the unit of processing delay.
        long sleepMillis = 0;
        for (long i = 0; i < delay.getMillis(); i++) {
          if (rnd.nextDouble() < cpuUtilizationInMixedDelay) {
            delay(Duration.millis(1), 0.0, SyntheticOptions.DelayType.CPU, rnd);
          } else {
            sleepMillis += delay(Duration.millis(1), 0.0, SyntheticOptions.DelayType.SLEEP, rnd);
          }
        }
        return sleepMillis;
      default:
        throw new IllegalArgumentException("Unknown delay type " + delayType);
    }
  }

  /** Keep cpu busy for {@code delayMillis} by calculating lots of hashes. */
  private static void cpuDelay(long delayMillis) {
    // Note that the delay is enforced in terms of walltime. That implies this thread may not
    // keep CPU busy if it gets preempted by other threads. There is more of chance of this
    // occurring in a streaming pipeline as there could be lots of threads running this. The loop
    // measures cpu time spent for each iteration, so that these effects are some what minimized.

    long cpuMicros = delayMillis * 1000;
    Stopwatch timer = Stopwatch.createUnstarted();

    while (timer.elapsed(TimeUnit.MICROSECONDS) < cpuMicros) {
      // Find a long which hashes to HASH in lowest MASK bits.
      // Values chosen to roughly take 1ms on typical workstation.
      timer.start();
      long p = INIT_PLAINTEXT;

View on GitHub (pinned to 12126d8942)