{"record":{"id":"490c0b6bcb14dda0","repo":"apache/beam","slug":"cannot-encode-elements-of-type-s-with-coder-s-the-generic","errorCode":null,"errorMessage":"Cannot encode elements of type %s with coder %s: the generic supertype %s has %s type parameters, which is less than the number of coder arguments %s has (%s).","messagePattern":"Cannot encode elements of type (.+?) with coder (.+?): the generic supertype (.+?) has (.+?) type parameters, which is less than the number of coder arguments (.+?) has \\((.+?)\\)\\.","errorType":"exception","errorClass":"IncompatibleCoderException","httpStatus":null,"severity":"error","filePath":"sdks/java/core/src/main/java/org/apache/beam/sdk/coders/CoderRegistry.java","lineNumber":559,"sourceCode":"              candidateType, coder, codedClass, candidateType),\n          coder,\n          candidateType);\n    }\n    // we have established that this is a covariant upcast... though\n    // coders are invariant, we are just checking one direction\n    @SuppressWarnings(\"unchecked\")\n    TypeDescriptor<T> candidateOkDescriptor = (TypeDescriptor<T>) candidateDescriptor;\n\n    // If the coded type is a parameterized type where any of the actual\n    // type parameters are not compatible, then the whole thing is certainly not\n    // compatible.\n    if ((codedType instanceof ParameterizedType) && !isNullOrEmpty(coder.getCoderArguments())) {\n      ParameterizedType parameterizedSupertype =\n          (ParameterizedType) candidateOkDescriptor.getSupertype(codedClass).getType();\n      Type[] typeArguments = parameterizedSupertype.getActualTypeArguments();\n      List<? extends Coder<?>> typeArgumentCoders = coder.getCoderArguments();\n      if (typeArguments.length < typeArgumentCoders.size()) {\n        throw new IncompatibleCoderException(\n            String.format(\n                \"Cannot encode elements of type %s with coder %s:\"\n                    + \" the generic supertype %s has %s type parameters, which is less than the\"\n                    + \" number of coder arguments %s has (%s).\",\n                candidateOkDescriptor,\n                coder,\n                parameterizedSupertype,\n                typeArguments.length,\n                coder,\n                typeArgumentCoders.size()),\n            coder,\n            candidateOkDescriptor.getType());\n      }\n      for (int i = 0; i < typeArgumentCoders.size(); i++) {\n        try {\n          Coder<?> typeArgumentCoder = typeArgumentCoders.get(i);\n          verifyCompatible(\n              typeArgumentCoder, candidateDescriptor.resolveType(typeArguments[i]).getType());","sourceCodeStart":541,"sourceCodeEnd":577,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/java/core/src/main/java/org/apache/beam/sdk/coders/CoderRegistry.java#L541-L577","documentation":"When verifying a parameterized coded type against a coder that itself has coder arguments, the registry resolves the coded class's generic supertype and compares its number of type parameters to the coder's argument count. If the supertype has fewer type parameters than the coder has coder arguments, structural verification is impossible and IncompatibleCoderException is thrown.","triggerScenarios":"verifyCompatible on a ParameterizedType whose coder returns a getCoderArguments list longer than the generic supertype's ActualTypeArguments length — typically a malformed custom coder claiming more component coders than its encoded type has generics.","commonSituations":"Writing a custom coder for a class with a changed number of type parameters after a refactor or library upgrade; implementing getCoderArguments with a hardcoded list that no longer matches the encoded class's generics.","solutions":["Make getCoderArguments return exactly one coder per type parameter of the encoded type.","Update the coder's encoded type declaration to match its coder arguments.","If the type genuinely has fewer parameters, drop the extra component coders."],"exampleFix":"// before\npublic List<Coder<?>> getCoderArguments() { return ImmutableList.of(keyCoder, valueCoder); } // encoded type has 1 param\n// after\npublic List<Coder<?>> getCoderArguments() { return ImmutableList.of(keyCoder); }","handlingStrategy":"validation","validationCode":"if (coder.getCoderArguments().size() > typeArgsOfEncodedClass.length) {\n  throw new IllegalStateException(\"coder has more component coders than type parameters\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep getCoderArguments in sync with the encoded class's generics.","Add tests that verify custom coders against their encoded TypeDescriptor.","Avoid hardcoding component coder lists."],"tags":["java","apache-beam","coders","generics"],"backgroundTag":"schema-validation-failed","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"}