apache/beam · error · UnsupportedOperationException
RecordId unsupported in
Error message
RecordId unsupported in %s
What it means
DoFnInvoker's default UnsupportedInvocationBehavior throws this when a DoFn callback calls currentRecordOffset() in a context where the invocation behavior does not support it. Record/offset access is only meaningful for splittable-DoFn element+restriction processing; runners or invocation contexts that don't supply bundle data reject the call. It signals that the DoFn is asking for bundle metadata the current execution mode cannot provide.
Solutions
- Remove the currentRecordOffset() call unless the DoFn is a genuine splittable DoFn (extends DoFn and is executed with the SDF expansion processElement+restriction)
- Test the DoFn with TestPipeline or DoFnTestUtils rather than invoking it directly with DoFnInvokers.invokerFor(...)
- Guard the accessor with a capability check (e.g. isBounded/Context information) and fall back to a no-op or logged skip when bundle data is unavailable
- Use an invoker whose InvocationBehavior supports bundle data (e.g. the runner's DoFnRunner) instead of the default UnsupportedInvocationBehavior
Example fix
// before
@ProcessElement
public void process(ProcessContext c, OffsetRangeTracker tracker) {
long off = c.currentRecordOffset();
}
// after
@ProcessElement
public void process(ProcessContext c) {
// use the element itself, not bundle metadata
T value = c.element();
} Defensive patterns
Strategy: validation
Validate before calling
// Before invoking the DoFn, ensure it is a splittable DoFn with bundle-data support,
// or invoke it through a runner-backed DoFnRunner rather than the default invoker:
if (!isSplittableDoFn(myDoFn)) {
throw new IllegalStateException("DoFn uses currentRecordOffset but is not a splittable DoFn");
} Type guard
boolean supportsBundleData(DoFnInvoker.BundlingContext ctx) {
return ctx != null && !ctx.getClass().getSimpleName().equals("UnsupportedInvocationBehavior");
} Try / catch
try {
long offset = context.currentRecordOffset();
} catch (UnsupportedOperationException e) {
// bundle data unavailable in this context; fall back
LOG.warn("currentRecordOffset unsupported here: {}", e.getMessage());
} Prevention
- Only use bundle-data accessors (currentRecord/currentRecordOffset) inside real splittable DoFn element processing
- Never invoke DoFns directly with DoFnInvokers.invokerFor(...) in production or tests; use TestPipeline or DoFnTestUtils
- Check runner documentation for splittable-DoFn/bundle-data support before using these APIs
When it happens
Trigger: Calling context.currentRecordOffset() (via a DoFnParameter or onBundleStart/Finish callbacks) when the DoFn is invoked with UnsupportedInvocationBehavior — e.g. via DoFnInvokers.tryInvokeSetUpProcessElementAndFinishBundle or a runner path that uses ProcessContext with no bundle data, or invoking a splittable-DoFn-only accessor from a non-DoFn runner context.
Common situations: Running a DoFn that uses splittable-DoFn bundle-data accessors (currentRecord, currentElement with restriction, currentRecordOffset) on a runner or test harness that does not provide bundle data; unit-testing such a DoFn with a plain invoker instead of DoFnTestUtils/TestPipeline; calling offset accessors outside onWindowExpiration or timer callbacks where they are unsupported.
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
- RecordOffset unsupported in
- ValueKind unsupported in
- Cannot access fire timestamp outside of @OnTimer method.
- Cannot access timerId as parameter outside of @OnTimer…
- CausedByDrain unsupported in
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/e8caff07313d00a9.
Report an issue: GitHub.
Appendix: source
Thrown at sdks/java/core/src/main/java/org/apache/beam/sdk/transforms/reflect/DoFnInvoker.java:354
throw new UnsupportedOperationException(
String.format("Schema element unsupported in %s", getErrorContext()));
}
@Override
public Instant timestamp(DoFn<InputT, OutputT> doFn) {
throw new UnsupportedOperationException(
String.format("Timestamp unsupported in %s", getErrorContext()));
}
@Override
public @Nullable String currentRecordId(DoFn<InputT, OutputT> doFn) {
throw new UnsupportedOperationException(
String.format("RecordId unsupported in %s", getErrorContext()));
}
@Override
public @Nullable Long currentRecordOffset(DoFn<InputT, OutputT> doFn) {
throw new UnsupportedOperationException(
String.format("RecordOffset unsupported in %s", getErrorContext()));
}
@Override
public Instant fireTimestamp(DoFn<InputT, OutputT> doFn) {
throw new UnsupportedOperationException(
String.format("FireTimestamp unsupported in %s", getErrorContext()));
}
@Override
public CausedByDrain causedByDrain(DoFn<InputT, OutputT> doFn) {
throw new UnsupportedOperationException(
String.format("CausedByDrain unsupported in %s", getErrorContext()));
}
@Override
public ValueKind valueKind(DoFn<InputT, OutputT> doFn) {
throw new UnsupportedOperationException(View on GitHub (pinned to 12126d8942)