{"record":{"id":"023945f465ac8534","repo":"apache/beam","slug":"cannot-serialize-the-combinefn-resulting-from-combinefnutil","errorCode":null,"errorMessage":"Cannot serialize the CombineFn resulting from CombineFnUtil.bindContext.","messagePattern":"Cannot serialize the CombineFn resulting from CombineFnUtil\\.bindContext\\.","errorType":"exception","errorClass":"NotSerializableException","httpStatus":null,"severity":"error","filePath":"sdks/java/core/src/main/java/org/apache/beam/sdk/util/CombineFnUtil.java","lineNumber":174,"sourceCode":"    public Coder<AccumT> getAccumulatorCoder(CoderRegistry registry, Coder<InputT> inputCoder)\n        throws CannotProvideCoderException {\n      return combineFn.getAccumulatorCoder(registry, inputCoder);\n    }\n\n    @Override\n    public Coder<OutputT> getDefaultOutputCoder(CoderRegistry registry, Coder<InputT> inputCoder)\n        throws CannotProvideCoderException {\n      return combineFn.getDefaultOutputCoder(registry, inputCoder);\n    }\n\n    @Override\n    public void populateDisplayData(DisplayData.Builder builder) {\n      combineFn.populateDisplayData(builder);\n    }\n\n    private void writeObject(@SuppressWarnings(\"unused\") ObjectOutputStream out)\n        throws IOException {\n      throw new NotSerializableException(\n          \"Cannot serialize the CombineFn resulting from CombineFnUtil.bindContext.\");\n    }\n  }\n}\n","sourceCodeStart":156,"sourceCodeEnd":179,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/java/core/src/main/java/org/apache/beam/sdk/util/CombineFnUtil.java#L156-L179","documentation":"CombineFnUtil.bindContext wraps a SerializableFunction<Context, CombineFn> in a BoundContext CombineFn whose context binding is inherently non-serializable, so its writeObject deliberately throws NotSerializableException. Instances of this wrapper must be created lazily/deserialized via the surrounding serialized lambda/function mechanism, never Java-serialized directly.","triggerScenarios":"Java-serializing the CombineFn returned by CombineFnUtil.bindContext — e.g. when a runner or DoFn graph serializes the object directly, or user code puts the bound CombineFn into an ObjectOutputStream, Kryo-with-java-serialization, or serialized closure capture.","commonSituations":"Serializing pipeline closures that captured the bound CombineFn by value; runners or test harnesses deep-copying PTransforms via Java serialization; caching the bound CombineFn in a serializable field.","solutions":["Serialize the underlying SerializableFunction (context -> CombineFn) instead of the bound wrapper, and call CombineFnUtil.bindContext after deserialization","Store the unbound CombineFn/lambda in serializable fields and bind the context at runtime inside the process method","Use the public Contextful API (CombineFnBase.Contextful / Contextful.of) which handles serialization of fn + context requirements","If a runner fails, check whether it java-serializes functions; configure it to use the supported Beam function serialization path"],"exampleFix":"// before\nprivate final CombineFn<MyIn, MyAcc, MyOut> fn =\n    CombineFnUtil.bindContext(myFnSupplier, realContext); // not serializable\n// after\nprivate final SerializableFunction<Context, CombineFn<MyIn, MyAcc, MyOut>> supplier =\n    ctx -> CombineFnUtil.bindContext(myFnSupplier, ctx); // bind at runtime, supplier is serializable","handlingStrategy":"try-catch","validationCode":"if (fn instanceof BoundContext) {\n  throw new IllegalStateException(\"Do not serialize the bound CombineFn; serialize the supplier\");\n}","typeGuard":"boolean isSerializableFn(Object o) {\n  return o instanceof Serializable && !(o.getClass().getSimpleName().equals(\"BoundContext\"));\n}","tryCatchPattern":"try (ObjectOutputStream out = new ObjectOutputStream(baos)) {\n  out.writeObject(fn);\n} catch (NotSerializableException e) {\n  // serialize the underlying SerializableFunction and rebind context instead\n}","preventionTips":["Store the unbound SerializableFunction and call bindContext at runtime","Never capture bound CombineFns in serialized closures","Prefer Beam's Contextful APIs for context-dependent combines","Test serialization round-trips of pipeline transforms in CI"],"tags":["java","serialization","beam","combine","notserializable"],"backgroundTag":"object-not-serializable","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"}