apache/beam · error · IllegalArgumentException
Class has parameters, but coders are requested.
Error message
Class %s has %d parameters, but %d coders are requested.
What it means
CoderRegistry.getDefaultCoders validates that the number of explicitly provided knownCoders matches the number of type parameters on the generic base class. A mismatch throws IllegalArgumentException 'Class %s has %d parameters, but %d coders are requested.' — e.g. passing 2 coders to getDefaultOutputCoder on a CombineFn with 3 type parameters.
Solutions
- Pass an array of known coders whose length equals the number of type parameters of baseClass (e.g. 3 for CombineFn<InputT, AccT, OutT>)
- Use null for knownCoders to let the registry fill all positions via inference instead of supplying a wrong-length array
- Check baseClass's declared generic signature and count its type arguments before constructing the coder array
Example fix
// before
registry.getDefaultOutputCoder(fn, CombineFn.class, new Coder<?>[]{c1}); // CombineFn has 3 params
// after
registry.getDefaultOutputCoder(fn, CombineFn.class, new Coder<?>[]{c1, c2, c3}); Defensive patterns
Strategy: validation
Validate before calling
int typeParamCount = baseClass.getTypeParameters().length;
if (knownCoders != null && knownCoders.length != typeParamCount) throw new IllegalArgumentException("Expected " + typeParamCount + " coders"); Type guard
boolean coderCountMatches = knownCoders == null || knownCoders.length == baseClass.getTypeParameters().length;
Prevention
- Count baseClass.getTypeParameters().length before building the coder array
- Pass null for knownCoders and rely on registry inference when unsure
- Add a test asserting getDefaultOutputCoder succeeds for each parameterized pipeline class
When it happens
Trigger: Calling getDefaultOutputCoder / getAccumulatorCoder / getDefaultCoders with a knownCoders array whose length differs from baseClass's actual type-argument count (e.g. 3 generic params on CombineFn but only 1–2 coders supplied).
Common situations: Mispredicting the number of type parameters of CombineFn/DoFn/KeyedCombineFn after a Beam version changed the class hierarchy; copy-pasted coder arrays reused across differently parameterized classes.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- cannot encode a null Instant
- cannot encode a null Iterable
- cannot encode a null
- cannot encode a null KV
- Cannot encode elements of type
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/8162e1742bf7dbec.
Report an issue: GitHub.
Appendix: source
Thrown at sdks/java/core/src/main/java/org/apache/beam/sdk/coders/CoderRegistry.java:434
* @param knownCoders an array corresponding to the set of base class type parameters. Each entry
* can be either a {@link Coder} (in which case it will be used for inference) or {@code null}
* (in which case it will be inferred). May be {@code null} to indicate the entire set of
* parameters should be inferred.
* @throws IllegalArgumentException if baseClass doesn't have type parameters or if the length of
* {@code knownCoders} is not equal to the number of type parameters of {@code baseClass}.
*/
private <T> Coder<?>[] getDefaultCoders(
Class<? extends T> subClass, Class<T> baseClass, @Nullable Coder<?>[] knownCoders) {
Type type = TypeDescriptor.of(subClass).getSupertype(baseClass).getType();
if (!(type instanceof ParameterizedType)) {
throw new IllegalArgumentException(type + " is not a ParameterizedType");
}
ParameterizedType parameterizedType = (ParameterizedType) type;
Type[] typeArgs = parameterizedType.getActualTypeArguments();
if (knownCoders == null) {
knownCoders = new Coder<?>[typeArgs.length];
} else if (typeArgs.length != knownCoders.length) {
throw new IllegalArgumentException(
String.format(
"Class %s has %d parameters, but %d coders are requested.",
baseClass.getCanonicalName(), typeArgs.length, knownCoders.length));
}
SetMultimap<Type, Coder<?>> context = HashMultimap.create();
for (int i = 0; i < knownCoders.length; i++) {
if (knownCoders[i] != null) {
try {
verifyCompatible(knownCoders[i], typeArgs[i]);
} catch (IncompatibleCoderException exn) {
throw new IllegalArgumentException(
String.format(
"Provided coders for type arguments of %s contain incompatibilities:"
+ " Cannot encode elements of type %s with coder %s",
baseClass, typeArgs[i], knownCoders[i]),
exn);
}View on GitHub (pinned to 12126d8942)