apache/beam · error · IllegalStateException
Could not determine coder for accumulator
Error message
Could not determine coder for accumulator
What it means
AppliedCombineFn.withInputCoder() clones the given GlobalCombineFn and asks it to infer a Coder for its accumulator via getAccumulatorCoder(registry, kvCoder.getValueCoder()). If the combine function cannot provide a coder (CannotProvideCoderException), the factory wraps it in an IllegalStateException('Could not determine coder for accumulator'). The CombineFn must be able to serialize its accumulator type for distributed execution.
Solutions
- Implement getAccumulatorCoder() in your CombineFn to return an explicit Coder (e.g. a SerializableCoder or custom Coder) instead of delegating/throwing.
- Register a default Coder for the accumulator type in the CoderRegistry (registry.registerCoder(AccumT.class, MyCoder.class)).
- Choose an accumulator type Beam can encode natively (KV, primitives, annotated with @DefaultSchema) so inference succeeds.
Example fix
// before
@Override public Coder<Accum> getAccumulatorCoder(CoderRegistry r, Coder<Input> in) throws CannotProvideCoderException {
throw new CannotProvideCoderException("no coder");
}
// after
@Override public Coder<Accum> getAccumulatorCoder(CoderRegistry r, Coder<Input> in) {
return SerializableCoder.of(Accum.class);
} Defensive patterns
Strategy: validation
Validate before calling
CoderRegistry registry = pipeline.getCoderRegistry(); registry.registerCoderForClass(MyAccum.class, MyAccumCoder.class); // or verify your CombineFn.getAccumulatorCoder does not throw CannotProvideCoderException
Try / catch
try {
AppliedCombineFn.withInputCoder(fn, registry, kvCoder, sideInputs);
} catch (IllegalStateException e) {
// fall back to a coder-explicit CombineFn implementation
} Prevention
- Always implement getAccumulatorCoder() explicitly in custom CombineFns.
- Register default coders for accumulator types in the CoderRegistry.
- Prefer accumulator types with natural encodings (primitives, KV, schemas).
When it happens
Trigger: Creating an AppliedCombineFn for a custom CombineFn whose getAccumulatorCoder throws CannotProvideCoderException — typically because the accumulator class has no registered default coder and the type is not one Beam can infer (e.g. a custom POJO without an encoded schema).
Common situations: Writing a custom CombineFn with an accumulator type like Optional, an interface, or a POJO lacking a registered Coder; registry in withInputCoder(CoderRegistry, ...) not containing coders for nested accumulator types.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- cannot encode a null BitSet
- cannot encode a null byte[]
- cannot encode a null Integer
- cannot encode a null Long
- cannot encode a null Short
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/5e82104c11485db6.
Report an issue: GitHub.
Appendix: source
Thrown at sdks/java/core/src/main/java/org/apache/beam/sdk/util/AppliedCombineFn.java:114
}
public static <K, InputT, AccumT, OutputT>
AppliedCombineFn<K, InputT, AccumT, OutputT> withInputCoder(
GlobalCombineFn<? super InputT, AccumT, OutputT> fn,
CoderRegistry registry,
KvCoder<K, InputT> kvCoder,
Iterable<PCollectionView<?>> sideInputViews,
WindowingStrategy<?, ?> windowingStrategy) {
// Casting down the K and InputT is safe because they're only used as inputs.
@SuppressWarnings("unchecked")
GlobalCombineFn<InputT, AccumT, OutputT> clonedFn =
(GlobalCombineFn<InputT, AccumT, OutputT>) SerializableUtils.clone(fn);
try {
Coder<AccumT> accumulatorCoder =
clonedFn.getAccumulatorCoder(registry, kvCoder.getValueCoder());
return create(clonedFn, accumulatorCoder, sideInputViews, kvCoder, windowingStrategy);
} catch (CannotProvideCoderException e) {
throw new IllegalStateException("Could not determine coder for accumulator", e);
}
}
private static <K, InputT, AccumT, OutputT> AppliedCombineFn<K, InputT, AccumT, OutputT> create(
GlobalCombineFn<InputT, AccumT, OutputT> fn,
Coder<AccumT> accumulatorCoder,
Iterable<PCollectionView<?>> sideInputViews,
KvCoder<K, InputT> kvCoder,
WindowingStrategy<?, ?> windowingStrategy) {
return new AppliedCombineFn<>(fn, accumulatorCoder, sideInputViews, kvCoder, windowingStrategy);
}
public GlobalCombineFn<InputT, AccumT, OutputT> getFn() {
return fn;
}
public Iterable<PCollectionView<?>> getSideInputViews() {
return sideInputViews;View on GitHub (pinned to 12126d8942)