{"record":{"id":"27a78f35c38a80f3","repo":"apache/beam","slug":"unknown-type-of-fn-class-s","errorCode":null,"errorMessage":"Unknown type of fn class %s","messagePattern":"Unknown type of fn class (.+?)","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"sdks/java/core/src/main/java/org/apache/beam/sdk/transforms/FlatMapElements.java","lineNumber":174,"sourceCode":"                      .getRequirements()\n                      .getSideInputs()));\n    } else if (fn instanceof ProcessFunction) {\n      return input.apply(\n          \"FlatMap\",\n          ParDo.of(\n              new FlatMapDoFn() {\n                @ProcessElement\n                public void processElement(\n                    @Element InputT element, OutputReceiver<OutputT> receiver) throws Exception {\n                  Iterable<OutputT> res =\n                      ((ProcessFunction<InputT, Iterable<OutputT>>) fn).apply(element);\n                  for (OutputT output : res) {\n                    receiver.output(output);\n                  }\n                }\n              }));\n    } else {\n      throw new IllegalArgumentException(\n          String.format(\"Unknown type of fn class %s\", fn.getClass()));\n    }\n  }\n\n  private abstract class FlatMapDoFn extends DoFn<InputT, OutputT> {\n\n    @Override\n    public TypeDescriptor<InputT> getInputTypeDescriptor() {\n      return inputType;\n    }\n\n    @Override\n    public TypeDescriptor<OutputT> getOutputTypeDescriptor() {\n      checkState(\n          outputType != null,\n          \"%s output type descriptor was null; \"\n              + \"this probably means that getOutputTypeDescriptor() was called after \"\n              + \"serialization/deserialization, but it is only available prior to \"","sourceCodeStart":156,"sourceCodeEnd":192,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/java/core/src/main/java/org/apache/beam/sdk/transforms/FlatMapElements.java#L156-L192","documentation":"FlatMapElements.via(fn) accepts only a few fn shapes: a function/SerializableFunction, or (in the failing expand) a specific class type it knows how to adapt into a DoFn. When the fn object is of any other class, expand throws this IllegalArgumentException.","triggerScenarios":"Calling FlatMapElements.via() with a fn whose runtime class is neither ProcessFunction/SerializableFunction nor one of the supported inner adapter classes (e.g. a class already carrying an output type not matching the expected type parameter).","commonSituations":"Type-erasure mistakes: passing a lambda assigned to a raw or wrong generic type; reusing a fn class from a different transform; calling via() with an anonymous class of unexpected shape.","solutions":["Pass a lambda or method reference typed as ProcessFunction<InputT, Iterable<OutputT>>","Ensure the generic type parameters of FlatMapElements.via(...) match the fn's input/output types","If using a class, implement SerializableFunction<InputT, Iterable<OutputT>> (or the required interface) directly"],"exampleFix":"// before\nFlatMapElements.via(new MyWeirdFn());\n// after\nFlatMapElements.via((ProcessFunction<String, Iterable<Integer>>) s -> Arrays.asList(s.split(\" \")))","handlingStrategy":"type-guard","validationCode":"// Verify the fn type before passing to FlatMapElements\nif (!(fn instanceof ProcessFunction) && !(fn instanceof SerializableFunction)) {\n  throw new IllegalArgumentException(\"fn must be a ProcessFunction/SerializableFunction\");\n}","typeGuard":"boolean isValidFlatMapFn(Object fn) {\n  return fn instanceof ProcessFunction || fn instanceof SerializableFunction;\n}","tryCatchPattern":"try { pc.apply(FlatMapElements.into(td).via(fn)); }\ncatch (IllegalArgumentException e) { log.error(\"bad fn class\", e); }","preventionTips":["Always pass lambdas or method references typed to ProcessFunction<InputT, Iterable<OutputT>>","Check generic type parameters match the FlatMapElements.into() type descriptor","Avoid raw types when declaring the fn variable"],"tags":["java","apache-beam","argument-validation","generics"],"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-14T16:17:12.679Z"}