{"record":{"id":"56a5dc32ad1a03f4","repo":"apache/beam","slug":"cannot-call-getpipelineoptions-in-a-null-context-56a5dc","errorCode":null,"errorMessage":"cannot call getPipelineOptions() in a null context","messagePattern":"cannot call getPipelineOptions\\(\\) in a null context","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"sdks/java/core/src/main/java/org/apache/beam/sdk/util/CombineContextFactory.java","lineNumber":34,"sourceCode":" * limitations under the License.\n */\npackage org.apache.beam.sdk.util;\n\nimport org.apache.beam.sdk.annotations.Internal;\nimport org.apache.beam.sdk.options.PipelineOptions;\nimport org.apache.beam.sdk.state.StateContext;\nimport org.apache.beam.sdk.transforms.CombineWithContext.Context;\nimport org.apache.beam.sdk.values.PCollectionView;\n\n/** Factory that produces {@code Combine.Context} based on different inputs. */\n@Internal\npublic class CombineContextFactory {\n\n  private static final Context NULL_CONTEXT =\n      new Context() {\n        @Override\n        public PipelineOptions getPipelineOptions() {\n          throw new IllegalArgumentException(\"cannot call getPipelineOptions() in a null context\");\n        }\n\n        @Override\n        public <T> T sideInput(PCollectionView<T> view) {\n          throw new IllegalArgumentException(\"cannot call sideInput() in a null context\");\n        }\n      };\n\n  /** Returns a fake {@code Combine.Context} for tests. */\n  public static Context nullContext() {\n    return NULL_CONTEXT;\n  }\n\n  /** Returns a {@code Combine.Context} that wraps a {@link StateContext}. */\n  public static Context createFromStateContext(final StateContext<?> c) {\n    return new Context() {\n      @Override\n      public PipelineOptions getPipelineOptions() {","sourceCodeStart":16,"sourceCodeEnd":52,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/java/core/src/main/java/org/apache/beam/sdk/util/CombineContextFactory.java#L16-L52","documentation":"CombineContextFactory.nullContext() returns a placeholder Combine.Context for tests whose getPipelineOptions() always throws IllegalArgumentException. Calling getPipelineOptions() on the null context is by definition unsupported: a null context represents 'no side inputs and no pipeline options available'.","triggerScenarios":"Calling context.getPipelineOptions() on the Context returned by CombineContextFactory.nullContext(), typically inside a custom CombineFn's addInput/mergeAccumulators/extractOutput when running in a test or a pipeline that supplied the null context.","commonSituations":"Unit-testing a CombineFn that reads PipelineOptions (e.g. custom config) using nullContext(); production code paths accidentally wired with nullContext via CombineFnUtil.bindContext with a null context.","solutions":["Test with a real Context that returns your PipelineOptions instead of nullContext()","Refactor the CombineFn to not require PipelineOptions when operating in the null context (guard with feature checks)","Create a minimal anonymous Context implementation returning a TestPipelineOptions or a stub PipelineOptions in tests","Verify CombineFnUtil.bindContext was not given a null context in production wiring"],"exampleFix":"// before\nContext ctx = CombineContextFactory.nullContext(); // throws on getPipelineOptions()\ncombineFn.addInput(ctx, acc, value);\n// after\nContext ctx = new Context() {\n  public PipelineOptions getPipelineOptions() { return testOptions; }\n  public <T> T sideInput(PCollectionView<T> v) { throw new UnsupportedOperationException(); }\n};\ncombineFn.addInput(ctx, acc, value);","handlingStrategy":"validation","validationCode":"Context ctx = CombineContextFactory.nullContext();\n// guard in CombineFn:\nif (useNullContext) { /* skip pipeline-options-dependent logic */ }","typeGuard":null,"tryCatchPattern":"try {\n  PipelineOptions opts = context.getPipelineOptions();\n} catch (IllegalArgumentException e) {\n  // null context: operate without pipeline options or fail fast with a clear message\n}","preventionTips":["Only use nullContext() for CombineFns that never touch options/side inputs","In tests, build a stub Context returning TestPipelineOptions","Check bindContext wiring passes a real context in production"],"tags":["java","beam","combine","testing","pipeline-options"],"backgroundTag":"unsupported-operation","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}