apache/beam · error · UnsupportedOperationException

Cannot access key as parameter outside of @OnTimer method.

Error message

Cannot access key as parameter outside of @OnTimer method.

What it means

The key() context parameter is only injectable inside @OnTimer methods (and keyed contexts). DoFnTester's ProcessContext throws UnsupportedOperationException if a @ProcessElement method declares the key as a parameter, because element processing in the tester isn't keyed.

Source

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

            public DoFn<InputT, OutputT>.FinishBundleContext finishBundleContext(
                DoFn<InputT, OutputT> doFn) {
              throw new UnsupportedOperationException(
                  "Not expected to access DoFn.FinishBundleContext from @ProcessElement");
            }

            @Override
            public DoFn<InputT, OutputT>.ProcessContext processContext(DoFn<InputT, OutputT> doFn) {
              return processContext;
            }

            @Override
            public InputT element(DoFn<InputT, OutputT> doFn) {
              return processContext.element();
            }

            @Override
            public Object key() {
              throw new UnsupportedOperationException(
                  "Cannot access key as parameter outside of @OnTimer method.");
            }

            @Override
            public Instant timestamp(DoFn<InputT, OutputT> doFn) {
              return processContext.timestamp();
            }

            @Override
            public String timerId(DoFn<InputT, OutputT> doFn) {
              throw new UnsupportedOperationException(
                  "Cannot access timerId as parameter outside of @OnTimer method.");
            }

            @Override
            public TimeDomain timeDomain(DoFn<InputT, OutputT> doFn) {
              throw new UnsupportedOperationException(
                  "Not expected to access TimeDomain from @ProcessElement");

View on GitHub (pinned to 12126d8942)

Solutions

  1. Access the key in @OnTimer methods only, or obtain the key from a KV input (c.element().getKey()) in @ProcessElement
  2. Remove the key parameter from @ProcessElement; use @Element KV<K,V> and extract the key
  3. For stateful processing tests, run via TestPipeline with a real runner instead of DoFnTester

Example fix

// before
@ProcessElement public void process(@Element KV<String, Integer> e, @Key String key) {...}
// after
@ProcessElement public void process(@Element KV<String, Integer> e) { String key = e.getKey(); ... }
Defensive patterns

Strategy: validation

Validate before calling

// key() is only injectable in @OnTimer contexts; derive key from KV in @ProcessElement
String key = kv.getKey();

Try / catch

try {
  tester.processElement();
} catch (UnsupportedOperationException e) {
  // @Key parameter used in @ProcessElement
}

Prevention

When it happens

Trigger: Declaring `Object key` (DoFn.Key parameter) in a @ProcessElement method and running it under DoFnTester.

Common situations: Testing stateful/timer DoFns with DoFnTester; accidentally requesting the key in element processing when the pipeline runs with unkeyed input.

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