{"record":{"id":"c8f110807d0dffc2","repo":"apache/flink","slug":"class-is-not-a-typeinfofactory","errorCode":null,"errorMessage":"Class is not a TypeInfoFactory.","messagePattern":"Class is not a TypeInfoFactory\\.","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"flink-core/src/main/java/org/apache/flink/api/common/serialization/SerializerConfigImpl.java","lineNumber":475,"sourceCode":"    private void parseAndRegisterTypeFactory(\n            ClassLoader classLoader, Class<?> t, Map<String, String> m) {\n        Class<? extends TypeInfoFactory<?>> factoryClass =\n                loadClass(m.get(\"class\"), classLoader, \"Could not load TypeInfoFactory's class\");\n        // Register in the global static factory map of TypeExtractor for now so that it can be\n        // accessed from the static methods of TypeExtractor where SerializerConfig is currently\n        // not accessible\n        TypeExtractor.registerFactory(t, factoryClass);\n        // Register inside SerializerConfig only for testing purpose for now\n        registerTypeWithTypeInfoFactory(t, factoryClass);\n    }\n\n    private void registerTypeWithTypeInfoFactory(\n            Class<?> t, Class<? extends TypeInfoFactory<?>> factory) {\n        Preconditions.checkNotNull(t, \"Type parameter must not be null.\");\n        Preconditions.checkNotNull(factory, \"Factory parameter must not be null.\");\n\n        if (!TypeInfoFactory.class.isAssignableFrom(factory)) {\n            throw new IllegalArgumentException(\"Class is not a TypeInfoFactory.\");\n        }\n        if (registeredTypeInfoFactories.containsKey(t)) {\n            throw new InvalidTypesException(\n                    \"A TypeInfoFactory for type '\" + t + \"' is already registered.\");\n        }\n        registeredTypeInfoFactories.put(t, factory);\n    }\n\n    @Override\n    public SerializerConfigImpl copy() {\n        final SerializerConfigImpl newSerializerConfig = new SerializerConfigImpl();\n        newSerializerConfig.configure(configuration, this.getClass().getClassLoader());\n\n        getRegisteredTypesWithKryoSerializers()\n                .forEach(\n                        (c, s) ->\n                                newSerializerConfig.registerTypeWithKryoSerializer(\n                                        c, s.getSerializer()));","sourceCodeStart":457,"sourceCodeEnd":493,"githubUrl":"https://github.com/apache/flink/blob/2f3c205e9266cb30240eb7f4fdab15cad629a70f/flink-core/src/main/java/org/apache/flink/api/common/serialization/SerializerConfigImpl.java#L457-L493","documentation":"Thrown by registerTypeWithTypeInfoFactory when the loaded factory class does not implement/extend TypeInfoFactory. The method first checks Preconditions.checkNotNull (for null) then verifies assignability. This guards the registeredTypeInfoFactories map against entries that would later fail during type extraction. The check uses TypeInfoFactory.class.isAssignableFrom(factory).","triggerScenarios":"Setting a typeinfo-type serialization-config entry whose 'class' points to a class that is not a TypeInfoFactory subclass. For example, pointing it at a regular TypeInformation class or a TypeSerializer by mistake.","commonSituations":"Confusing TypeInfoFactory with TypeInformation or TypeSerializer; pointing the factory class at a utility class; copy-paste of the wrong class name from documentation.","solutions":["Ensure the class referenced in the 'class' field extends TypeInfoFactory<?> and implements the createTypeInfo method.","If you meant to register a custom serializer, use type 'kryo' or 'pojo' instead of 'typeinfo'.","Verify with a unit test: TypeInfoFactory.class.isAssignableFrom(MyFactory.class)."],"exampleFix":"# before (wrong class)\npipeline.serialization-config: \"class:com.example.MyType{type:typeinfo,class:com.example.MyTypeInformation}\"\n\n// Implement a TypeInfoFactory\npublic class MyTypeInfoFactory extends TypeInfoFactory<MyType> {\n    @Override\n    public TypeInformation<MyType> createTypeInfo(Type t, Map<String, TypeInformation<?>> context) {\n        return new MyTypeInfo();\n    }\n}\n\n# after\npipeline.serialization-config: \"class:com.example.MyType{type:typeinfo,class:com.example.MyTypeInfoFactory}\"","handlingStrategy":"validation","validationCode":"Class<?> factoryClass = Class.forName(factoryName);\nif (!TypeInfoFactory.class.isAssignableFrom(factoryClass)) {\n    throw new IllegalArgumentException(\n        factoryName + \" does not extend TypeInfoFactory\");\n}","typeGuard":"public static boolean isTypeInfoFactory(Class<?> clazz) {\n    return clazz != null && TypeInfoFactory.class.isAssignableFrom(clazz);\n}","tryCatchPattern":null,"preventionTips":["Verify the factory class extends TypeInfoFactory<?> before configuring it.","Do not confuse TypeInfoFactory with TypeInformation or TypeSerializer."],"tags":["serialization","type-information","typeinfo-factory","validation"],"backgroundTag":null,"analyzedSha":"2f3c205e9266cb30240eb7f4fdab15cad629a70f","analyzedAt":"2026-08-14T08:48:24.518Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}