{"record":{"id":"bc0dccc1a2db8aac","repo":"apache/beam","slug":"sideinput-unsupported-in-context","errorCode":null,"errorMessage":"SideInput unsupported in ${context}","messagePattern":"SideInput unsupported in (.+?)","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"sdks/java/core/src/main/java/org/apache/beam/sdk/transforms/reflect/DoFnInvoker.java","lineNumber":324,"sourceCode":"      throw new UnsupportedOperationException(\n          String.format(\"ProcessContext unsupported in %s\", getErrorContext()));\n    }\n\n    @Override\n    public InputT element(DoFn<InputT, OutputT> doFn) {\n      throw new UnsupportedOperationException(\n          String.format(\"Element unsupported in %s\", getErrorContext()));\n    }\n\n    @Override\n    public @Nullable Object key() {\n      throw new UnsupportedOperationException(\n          \"Cannot access key as parameter outside of @OnTimer method.\");\n    }\n\n    @Override\n    public @Nullable Object sideInput(String tagId) {\n      throw new UnsupportedOperationException(\n          String.format(\"SideInput unsupported in %s\", getErrorContext()));\n    }\n\n    @Override\n    public TimerMap timerFamily(String tagId) {\n      throw new UnsupportedOperationException(\n          String.format(\"TimerFamily unsupported in %s\", getErrorContext()));\n    }\n\n    @Override\n    public @Nullable Object schemaElement(int index) {\n      throw new UnsupportedOperationException(\n          String.format(\"Schema element unsupported in %s\", getErrorContext()));\n    }\n\n    @Override\n    public Instant timestamp(DoFn<InputT, OutputT> doFn) {\n      throw new UnsupportedOperationException(","sourceCodeStart":306,"sourceCodeEnd":342,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/java/core/src/main/java/org/apache/beam/sdk/transforms/reflect/DoFnInvoker.java#L306-L342","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\n@StartBundle\npublic void startBundle(StartBundleContext c) {\n  double threshold = (Double) c.sideInput(\"threshold\"); // throws\n}\n\n// after\n@ProcessElement\npublic void processElement(ProcessContext c) {\n  double threshold = (Double) c.sideInput(\"threshold\");\n  process(c, threshold);\n}","handlingStrategy":"validation","validationCode":"// Validate at pipeline construction time that side inputs are only used in @ProcessElement.\nDoFnSignature sig = DoFnSignatures.getSignature(doFn.getClass());\nif (!sig.processElement().sideInputs().isEmpty() && !sig.processElement().isPresent()) {\n  throw new IllegalArgumentException(\"sideInput may only be used in @ProcessElement\");\n}","typeGuard":"// Narrow to the context that supports side inputs before calling.\nif (context instanceof DoFn.ProcessContext) {\n  Object v = ((DoFn.ProcessContext) context).sideInput(\"tag\");\n}","tryCatchPattern":"try {\n  Object v = context.sideInput(\"tag\");\n} catch (UnsupportedOperationException e) {\n  // sideInput not available in this lifecycle phase; use fallback value\n  Object v = defaultValue;\n}","preventionTips":["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."],"tags":["apache-beam","java","unsupported-operation","side-input","dofn"],"backgroundTag":"unsupported-operation","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}