apache/beam · error · UnsupportedOperationException

%s is splittable and uses state, but these are not compatibl

Error message

%s is splittable and uses state, but these are not compatible

What it means

ParDo.validate inspects the DoFn signature at pipeline construction time and rejects DoFns that both declare state and are splittable, because Beam's model considers splitting an element incompatible with per-element state semantics. The transform cannot be built and construction fails with UnsupportedOperationException.

Source

Thrown at sdks/java/core/src/main/java/org/apache/beam/sdk/transforms/ParDo.java:618

          methodSignature.windowT().isSupertypeOf(actualWindowT),
          "%s unable to provide window -- expected window type from parameter (%s) is not a "
              + "supertype of actual window type assigned by windowing (%s)",
          methodSignature.targetMethod(),
          methodSignature.windowT(),
          actualWindowT);
    }
  }

  /**
   * Perform common validations of the {@link DoFn}, for example ensuring that state is used
   * correctly and that its features can be supported.
   */
  private static <InputT, OutputT> void validate(DoFn<InputT, OutputT> fn) {
    DoFnSignature signature = DoFnSignatures.getSignature((Class) fn.getClass());

    // State is semantically incompatible with splitting
    if (!signature.stateDeclarations().isEmpty() && signature.processElement().isSplittable()) {
      throw new UnsupportedOperationException(
          String.format(
              "%s is splittable and uses state, but these are not compatible",
              fn.getClass().getName()));
    }

    // Timers are semantically incompatible with splitting
    if ((!signature.timerDeclarations().isEmpty() || !signature.timerFamilyDeclarations().isEmpty())
        && signature.processElement().isSplittable()) {
      throw new UnsupportedOperationException(
          String.format(
              "%s is splittable and uses timers, but these are not compatible",
              fn.getClass().getName()));
    }

    // TimerFamily is semantically incompatible with splitting
    if (!signature.timerFamilyDeclarations().isEmpty()
        && signature.processElement().isSplittable()) {
      throw new UnsupportedOperationException(

View on GitHub (pinned to 12126d8942)

Solutions

  1. Remove the state declarations from the splittable DoFn, or remove splittable processing (RestrictionTracker) from the stateful DoFn
  2. Split the logic into two DoFns: a splittable one producing elements, then a separate stateful ParDo
  3. Restructure to track progress via the restriction itself rather than persistent state

Example fix

// before
class Sdf extends DoFn<T, O> { @StateId ... ; @ProcessElement ProcessContinuation processElement(RestrictionTracker r, ...) }
// after
class Sdf extends DoFn<T, O> { @ProcessElement ProcessContinuation processElement(RestrictionTracker r, ...) } // state moved to downstream stateful DoFn
Defensive patterns

Strategy: validation

Validate before calling

DoFnSignature sig = DoFnSignatures.getSignature((Class) fn.getClass());
if (!sig.stateDeclarations().isEmpty() && sig.processElement().isSplittable()) {
  throw new IllegalArgumentException(fn.getClass() + " cannot use state and be splittable");
}

Type guard

boolean stateAndSplittable(DoFn<?, ?> fn) {
  DoFnSignature sig = DoFnSignatures.getSignature((Class) fn.getClass());
  return !sig.stateDeclarations().isEmpty() && sig.processElement().isSplittable();
}

Try / catch

try {
  pipeline.apply(ParDo.of(fn));
} catch (UnsupportedOperationException e) {
  if (e.getMessage() != null && e.getMessage().endsWith("splittable and uses state, but these are not compatible")) {
    throw new IllegalStateException("Split into splittable read + separate stateful ParDo", e);
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling ParDo.of(fn) (which invokes validate) where fn's class declares @StateId fields AND its @ProcessElement is splittable (has a RestrictionTracker / @GetInitialRestriction watermarks etc.).

Common situations: Adding @StateId to an existing splittable DoFn (e.g. a file/splittable reader DoFn) assuming state works; combining libraries' SDF patterns with stateful processing.

Understand the failure class

Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.

Related errors


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