apache/beam · error · UnsupportedOperationException

Not expected to access RestrictionTracker from a regular DoF

Error message

Not expected to access RestrictionTracker from a regular DoFn in DoFnTester

What it means

DoFnTester only provides a RestrictionTracker for splittable DoFns. For a regular DoFn, its ProcessContext.restrictionTracker() is hardcoded to throw this UnsupportedOperationException since no restriction tracking exists.

Source

Thrown at sdks/java/core/src/main/java/org/apache/beam/sdk/transforms/DoFnTester.java:350

            public OutputReceiver<OutputT> outputReceiver(DoFn<InputT, OutputT> doFn) {
              return DoFnOutputReceivers.windowedReceiver(processContext, builderSupplier, null);
            }

            @Override
            public MultiOutputReceiver taggedOutputReceiver(DoFn<InputT, OutputT> doFn) {
              return DoFnOutputReceivers.windowedMultiReceiver(
                  processContext, builderSupplier, null);
            }

            @Override
            public Object restriction() {
              throw new UnsupportedOperationException(
                  "Not expected to access Restriction from a regular DoFn in DoFnTester");
            }

            @Override
            public RestrictionTracker<?, ?> restrictionTracker() {
              throw new UnsupportedOperationException(
                  "Not expected to access RestrictionTracker from a regular DoFn in DoFnTester");
            }
          });
    } catch (UserCodeException e) {
      unwrapUserCodeException(e);
    }
  }

  /**
   * @deprecated Use {@link TestPipeline} with the {@code DirectRunner}.
   */
  @Deprecated
  public void finishBundle() throws Exception {
    checkState(
        state == State.BUNDLE_STARTED,
        "Must be inside bundle to call finishBundle, but was: %s",
        state);
    try {

View on GitHub (pinned to 12126d8942)

Solutions

  1. Drop the restrictionTracker() call for regular DoFns
  2. For splittable DoFns, test restriction tracking with a full pipeline run (TestPipeline) or a runner-level harness, not DoFnTester
  3. Refactor shared test code so SDF-specific assertions only run when the fn implements splittable processing

Example fix

// before
RestrictionTracker<?, ?> t = tester.processContext.restrictionTracker();
// after
// assert element outputs instead
assertThat(tester.takeOutputElements(), contains(in));
Defensive patterns

Strategy: try-catch

Validate before calling

// Guard: only splittable DoFns have restriction trackers
if (isSplittable(myDoFn)) { tester.processContext.restrictionTracker(); }

Type guard

boolean hasRestrictionTracker(DoFn<?, ?> fn) {
  return java.util.Arrays.stream(fn.getClass().getDeclaredMethods())
      .anyMatch(m -> m.isAnnotationPresent(DoFn.GetInitialRestriction.class));
}

Try / catch

try { RestrictionTracker<?, ?> t = ctx.restrictionTracker(); }
catch (UnsupportedOperationException e) { assert fnIsNotSplittable; }

Prevention

When it happens

Trigger: Invoking restrictionTracker() on the context of a DoFnTester that wraps a non-splittable DoFn.

Common situations: Tests written for splittable DoFns (with claim/restriction logic) being reused for plain DoFns; mistakenly asserting on the tracker in a regular DoFn unit test.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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