apache/beam · error · RuntimeException

Unexpected time domain

Error message

Unexpected time domain 

What it means

FnApiTimerBundleTracker.getModifiedTimersOrdered dispatches on the timer's TimeDomain to return the modified timers in order. If the time domain is none of EVENT_TIME, PROCESSING_TIME, or SYNCHRONIZED_PROCESSING_TIME (e.g. an unknown enum from a newer proto or an unset field), it throws a RuntimeException. This is an internal exhaustive-switch guard.

Solutions

  1. Align runner and SDK harness versions so the TimeDomain enum is understood.
  2. Inspect the timer payload/timers sent by the runner for an unset or unknown domain.
  3. Upgrade Beam to a release handling the domain listed in the failure.
  4. If custom runner integration, restrict emitted domains to the three standard ones.

Example fix

// before: reading raw proto enum without default handling
// after: upgrade harness to enumerate new domains
switch (domain) {
  case EVENT_TIME: ...;
  case PROCESSING_TIME: ...;
  case SYNCHRONIZED_PROCESSING_TIME: ...;
  default: /* upgrade or reject */ 
}
Defensive patterns

Strategy: try-catch

Type guard

boolean isKnownDomain(TimeDomain d) {
  return d == TimeDomain.EVENT_TIME
      || d == TimeDomain.PROCESSING_TIME
      || d == TimeDomain.SYNCHRONIZED_PROCESSING_TIME;
}

Try / catch

try {
  // timer handling
} catch (RuntimeException e) {
  if (e.getMessage() != null && e.getMessage().startsWith("Unexpected time domain")) {
    LOG.error("Unknown TimeDomain from runner: {}", e.getMessage(), e);
  } else { throw e; }
}

Prevention

When it happens

Trigger: A timer fire or timer modification carries a TimeDomain value outside the three known domains when the tracker collects ordered modified timers for bundle completion.

Common situations: Runner emitting newer TimeDomain enum values against an older harness; null/unset time domain from a malformed timer update; version-skewed deployments.

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/ee036e11af896788. Report an issue: GitHub.

Appendix: source

Thrown at sdks/java/harness/src/main/java/org/apache/beam/fn/harness/state/FnApiTimerBundleTracker.java:79

  @AutoValue
  public abstract static class Modifications<K> {
    public abstract NavigableSet<TimerInfo<K>> getModifiedEventTimersOrdered();

    public abstract NavigableSet<TimerInfo<K>> getModifiedProcessingTimersOrdered();

    public abstract NavigableSet<TimerInfo<K>> getModifiedSynchronizedProcessingTimersOrdered();

    public NavigableSet<TimerInfo<K>> getModifiedTimersOrdered(TimeDomain timeDomain) {
      switch (timeDomain) {
        case EVENT_TIME:
          return getModifiedEventTimersOrdered();
        case PROCESSING_TIME:
          return getModifiedProcessingTimersOrdered();
        case SYNCHRONIZED_PROCESSING_TIME:
          return getModifiedSynchronizedProcessingTimersOrdered();
        default:
          throw new RuntimeException("Unexpected time domain " + timeDomain);
      }
    }

    public abstract Table<String, String, Timer<K>> getModifiedTimerIds();

    @SuppressWarnings({"nullness"})
    static <K> Modifications<K> create() {
      Comparator<TimeDomain> timeDomainComparator =
          (td1, td2) -> {
            // We prioritize processing-time timers,as those tend to be more latency sensitive.
            if (td1 == TimeDomain.PROCESSING_TIME && td2 == TimeDomain.EVENT_TIME) {
              return -1;
            } else if (td1 == TimeDomain.EVENT_TIME && td2 == TimeDomain.PROCESSING_TIME) {
              return 1;
            } else {
              return td1.compareTo(td2);
            }
          };

View on GitHub (pinned to 12126d8942)