apache/beam · error · UnsupportedOperationException
SideInput unsupported in ${context}
Error message
SideInput unsupported in ${context} What it means
This UnsupportedOperationException is thrown by DoFnInvoker.BaseArgumentProvider.sideInput when a DoFn lifecycle method tries to bind a side input parameter in a context that does not support it. Beam's reflection-based invoker uses context-specific ArgumentProvider subclasses (StartBundle, ProcessElement, OnTimer, FinishBundle) that override only the accessors valid for that context; any accessor left un-overridden falls through to BaseArgumentProvider, which always throws. Side inputs are only resolvable during @ProcessElement processing, so other contexts deliberately reject them.
Source
Thrown at sdks/java/core/src/main/java/org/apache/beam/sdk/transforms/reflect/DoFnInvoker.java:324
throw new UnsupportedOperationException(
String.format("ProcessContext unsupported in %s", getErrorContext()));
}
@Override
public InputT element(DoFn<InputT, OutputT> doFn) {
throw new UnsupportedOperationException(
String.format("Element unsupported in %s", getErrorContext()));
}
@Override
public @Nullable Object key() {
throw new UnsupportedOperationException(
"Cannot access key as parameter outside of @OnTimer method.");
}
@Override
public @Nullable Object sideInput(String tagId) {
throw new UnsupportedOperationException(
String.format("SideInput unsupported in %s", getErrorContext()));
}
@Override
public TimerMap timerFamily(String tagId) {
throw new UnsupportedOperationException(
String.format("TimerFamily unsupported in %s", getErrorContext()));
}
@Override
public @Nullable Object schemaElement(int index) {
throw new UnsupportedOperationException(
String.format("Schema element unsupported in %s", getErrorContext()));
}
@Override
public Instant timestamp(DoFn<InputT, OutputT> doFn) {
throw new UnsupportedOperationException(View on GitHub (pinned to 12126d8942)
Solutions
- Move the c.sideInput("tag") call (or the @SideInput annotated parameter) into the @ProcessElement method, where side inputs are supported.
- If the value is needed in @StartBundle/@FinishBundle, pass it as a plain field computed in @ProcessElement, or read it from a @Setup-time source that does not depend on side inputs.
- For @OnTimer, access only supported parameters (key, timer, fire timestamp); side inputs are not provided at timer firing time.
- If writing a custom ArgumentProvider (test harness / runner), override sideInput(String) to return the actual value instead of inheriting the BaseArgumentProvider default.
Example fix
// before
@StartBundle
public void startBundle(StartBundleContext c) {
double threshold = (Double) c.sideInput("threshold"); // throws
}
// after
@ProcessElement
public void processElement(ProcessContext c) {
double threshold = (Double) c.sideInput("threshold");
process(c, threshold);
} Defensive patterns
Strategy: validation
Validate before calling
// Validate at pipeline construction time that side inputs are only used in @ProcessElement.
DoFnSignature sig = DoFnSignatures.getSignature(doFn.getClass());
if (!sig.processElement().sideInputs().isEmpty() && !sig.processElement().isPresent()) {
throw new IllegalArgumentException("sideInput may only be used in @ProcessElement");
} Type guard
// Narrow to the context that supports side inputs before calling.
if (context instanceof DoFn.ProcessContext) {
Object v = ((DoFn.ProcessContext) context).sideInput("tag");
} Try / catch
try {
Object v = context.sideInput("tag");
} catch (UnsupportedOperationException e) {
// sideInput not available in this lifecycle phase; use fallback value
Object v = defaultValue;
} Prevention
- Only call sideInput() from @ProcessElement methods.
- Never pass side inputs into @StartBundle/@FinishBundle/@OnTimer methods; pass plain values instead.
- Read the DoFn parameter-binding docs to confirm which parameters each lifecycle annotation supports.
When it happens
Trigger: Declaring a DoFn sideInput parameter (e.g. c.sideInput("tag")) or a @SideInput-annotated argument in a method whose invocation context's ArgumentProvider does not override sideInput, such as @StartBundle, @FinishBundle, @OnTimer, or @OnWindowExpiration methods. This happens inside DoFnInvoker.invokeProcessMethod when it resolves the method's parameters against the context's ArgumentProvider.
Common situations: Refactoring a parameter lookup from a @ProcessElement method into a @StartBundle/@FinishBundle setup method (e.g. pre-loading a side input once per bundle); using side inputs inside @OnTimer callbacks expecting them to be available; custom runner or test ArgumentProvider subclasses that extend BaseArgumentProvider without overriding sideInput.
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
- Not expected to access Restriction from a regular DoFn in Do
- Not expected to access RestrictionTracker from a regular DoF
- TimerFamily unsupported in ${context}
- Schema element unsupported in ${context}
- Timestamp unsupported in ${context}
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/bc0dccc1a2db8aac.
Report an issue: GitHub.