{"record":{"id":"8162e1742bf7dbec","repo":"apache/beam","slug":"class-s-has-d-parameters-but-d-coders-are-requested","errorCode":null,"errorMessage":"Class %s has %d parameters, but %d coders are requested.","messagePattern":"Class (.+?) has (.+?) parameters, but (.+?) coders are requested\\.","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"sdks/java/core/src/main/java/org/apache/beam/sdk/coders/CoderRegistry.java","lineNumber":434,"sourceCode":"   * @param knownCoders an array corresponding to the set of base class type parameters. Each entry\n   *     can be either a {@link Coder} (in which case it will be used for inference) or {@code null}\n   *     (in which case it will be inferred). May be {@code null} to indicate the entire set of\n   *     parameters should be inferred.\n   * @throws IllegalArgumentException if baseClass doesn't have type parameters or if the length of\n   *     {@code knownCoders} is not equal to the number of type parameters of {@code baseClass}.\n   */\n  private <T> Coder<?>[] getDefaultCoders(\n      Class<? extends T> subClass, Class<T> baseClass, @Nullable Coder<?>[] knownCoders) {\n    Type type = TypeDescriptor.of(subClass).getSupertype(baseClass).getType();\n    if (!(type instanceof ParameterizedType)) {\n      throw new IllegalArgumentException(type + \" is not a ParameterizedType\");\n    }\n    ParameterizedType parameterizedType = (ParameterizedType) type;\n    Type[] typeArgs = parameterizedType.getActualTypeArguments();\n    if (knownCoders == null) {\n      knownCoders = new Coder<?>[typeArgs.length];\n    } else if (typeArgs.length != knownCoders.length) {\n      throw new IllegalArgumentException(\n          String.format(\n              \"Class %s has %d parameters, but %d coders are requested.\",\n              baseClass.getCanonicalName(), typeArgs.length, knownCoders.length));\n    }\n\n    SetMultimap<Type, Coder<?>> context = HashMultimap.create();\n    for (int i = 0; i < knownCoders.length; i++) {\n      if (knownCoders[i] != null) {\n        try {\n          verifyCompatible(knownCoders[i], typeArgs[i]);\n        } catch (IncompatibleCoderException exn) {\n          throw new IllegalArgumentException(\n              String.format(\n                  \"Provided coders for type arguments of %s contain incompatibilities:\"\n                      + \" Cannot encode elements of type %s with coder %s\",\n                  baseClass, typeArgs[i], knownCoders[i]),\n              exn);\n        }","sourceCodeStart":416,"sourceCodeEnd":452,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/java/core/src/main/java/org/apache/beam/sdk/coders/CoderRegistry.java#L416-L452","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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"],"exampleFix":"// before\nregistry.getDefaultOutputCoder(fn, CombineFn.class, new Coder<?>[]{c1}); // CombineFn has 3 params\n// after\nregistry.getDefaultOutputCoder(fn, CombineFn.class, new Coder<?>[]{c1, c2, c3});","handlingStrategy":"validation","validationCode":"int typeParamCount = baseClass.getTypeParameters().length;\nif (knownCoders != null && knownCoders.length != typeParamCount) throw new IllegalArgumentException(\"Expected \" + typeParamCount + \" coders\");","typeGuard":"boolean coderCountMatches = knownCoders == null || knownCoders.length == baseClass.getTypeParameters().length;","tryCatchPattern":null,"preventionTips":["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"],"tags":["java","apache-beam","coders","argument-count"],"backgroundTag":"invalid-argument-value","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-20T03:17:13.778Z"}