{"record":{"id":"366fc8ed028ab20d","repo":"apache/beam","slug":"cannot-register-coder-method-named-of-with-arguments-of-366fc8","errorCode":null,"errorMessage":"cannot register Coder : method named 'of' with  arguments of Coder type does not return a ","messagePattern":"cannot register Coder : method named 'of' with  arguments of Coder type does not return a ","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"sdks/java/core/src/main/java/org/apache/beam/sdk/coders/CoderProviders.java","lineNumber":134,"sourceCode":"            \"cannot register Coder \"\n                + coderClazz\n                + \": \"\n                + \"does not have an accessible method named 'of' with \"\n                + numTypeParameters\n                + \" arguments of Coder type\",\n            exn);\n      }\n      if (!Modifier.isStatic(factoryMethodCandidate.getModifiers())) {\n        throw new IllegalArgumentException(\n            \"cannot register Coder \"\n                + coderClazz\n                + \": \"\n                + \"method named 'of' with \"\n                + numTypeParameters\n                + \" arguments of Coder type is not static\");\n      }\n      if (!coderClazz.isAssignableFrom(factoryMethodCandidate.getReturnType())) {\n        throw new IllegalArgumentException(\n            \"cannot register Coder \"\n                + coderClazz\n                + \": \"\n                + \"method named 'of' with \"\n                + numTypeParameters\n                + \" arguments of Coder type does not return a \"\n                + coderClazz);\n      }\n      try {\n        if (!factoryMethodCandidate.isAccessible()) {\n          factoryMethodCandidate.setAccessible(true);\n        }\n      } catch (SecurityException exn) {\n        throw new IllegalArgumentException(\n            \"cannot register Coder \"\n                + coderClazz\n                + \": \"\n                + \"method named 'of' with \"","sourceCodeStart":116,"sourceCodeEnd":152,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/java/core/src/main/java/org/apache/beam/sdk/coders/CoderProviders.java#L116-L152","documentation":"getFactoryMethod verifies that the `of` method's return type is assignable to the Coder class being registered (coderClazz.isAssignableFrom(returnType)). If `of` returns some other type — e.g. raw Coder of a different class, Object, or a sibling coder type — registration fails with this IllegalArgumentException because the provider could not return a coder of the expected class.","triggerScenarios":"CoderProviders.fromStaticMethods(rawType, coderClazz) where coderClazz declares `static X of(Coder...)` with X not a subclass of coderClazz, e.g. `of` declared in a superclass or interface returning the supertype, or returning a different concrete Coder class.","commonSituations":"Putting the generic `static <T> Coder<T> of(...)` in an abstract base class and registering concrete subclasses whose inherited `of` returns the base Coder type; raw-type returns after refactoring generics; a factory that builds a different coder implementation than the registered class.","solutions":["Change `of`'s declared return type to the registering class itself: `public static <T> MyCoder<T> of(Coder<T> c)`","If `of` lives in a superclass, override it in coderClazz with a covariant return type of coderClazz","Ensure generics are not erased to a supertype (avoid raw `Coder` returns; use `MyCoder<T>`)","Register the coder the `of` method actually builds with CoderProviders.fromStaticMethods against that class instead"],"exampleFix":"// before: inherited from base, returns base type\nstatic <T> Coder<T> of(Coder<T> c) { return new MyCoder<>(c); }\n// after: covariant override in MyCoder\npublic static <T> MyCoder<T> of(Coder<T> c) { return new MyCoder<>(c); }","handlingStrategy":"type-guard","validationCode":"static boolean ofReturnsOwnCoder(Class<?> coderClazz) throws NoSuchMethodException {\n  Class<?>[] argTypes = new Class<?>[coderClazz.getTypeParameters().length];\n  java.util.Arrays.fill(argTypes, Coder.class);\n  return coderClazz.isAssignableFrom(\n      coderClazz.getDeclaredMethod(\"of\", argTypes).getReturnType());\n}","typeGuard":"static boolean validFactorySignature(Class<?> coderClazz) {\n  try {\n    Class<?>[] argTypes = new Class<?>[coderClazz.getTypeParameters().length];\n    java.util.Arrays.fill(argTypes, Coder.class);\n    Method of = coderClazz.getDeclaredMethod(\"of\", argTypes);\n    return java.lang.reflect.Modifier.isStatic(of.getModifiers())\n        && coderClazz.isAssignableFrom(of.getReturnType());\n  } catch (NoSuchMethodException | SecurityException e) { return false; }\n}","tryCatchPattern":"try {\n  CoderProvider provider = CoderProviders.fromStaticMethods(rawType, coderClazz);\n} catch (IllegalArgumentException e) {\n  if (e.getMessage().contains(\"does not return a\")) {\n    throw new IllegalStateException(\"of() must return \" + coderClazz.getName(), e);\n  }\n  throw e;\n}","preventionTips":["Declare of()'s return type as the concrete coder class, not a supertype like Coder<T>","Override inherited generic factories with covariant return types in concrete coder classes","Avoid raw types in factory return declarations","Verify with a compile-time test: MyCoder c = MyCoder.of(...);"],"tags":["java","reflection","coders","apache-beam","type-safety"],"backgroundTag":"type-mismatch","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"}