{"record":{"id":"0cf645dd986edf92","repo":"apache/flink","slug":"a-typeinfofactory-for-type-is-already-registe","errorCode":null,"errorMessage":"A TypeInfoFactory for type '{}' is already registered.","messagePattern":"A TypeInfoFactory for type '(.+?)' is already registered\\.","errorType":"validation","errorClass":"InvalidTypesException","httpStatus":null,"severity":"error","filePath":"flink-core/src/main/java/org/apache/flink/api/common/serialization/SerializerConfigImpl.java","lineNumber":478,"sourceCode":"                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()));\n        getRegisteredTypesWithKryoSerializerClasses()\n                .forEach(newSerializerConfig::registerTypeWithKryoSerializer);\n        getDefaultKryoSerializers()","sourceCodeStart":460,"sourceCodeEnd":496,"githubUrl":"https://github.com/apache/flink/blob/2f3c205e9266cb30240eb7f4fdab15cad629a70f/flink-core/src/main/java/org/apache/flink/api/common/serialization/SerializerConfigImpl.java#L460-L496","documentation":"Thrown by registerTypeWithTypeInfoFactory (as InvalidTypesException) when a TypeInfoFactory is already registered for the given type. The registeredTypeInfoFactories map allows only one factory per type; a second registration indicates a conflict. This commonly arises from duplicate config entries or from registering the same type via both the API and the serialization-config.","triggerScenarios":"Calling registerTypeWithTypeInfoFactory twice for the same type Class, or having two serialization-config entries with type 'typeinfo' for the same class. The containsKey check fires before the put.","commonSituations":"Duplicate typeinfo entries in the serialization-config string; programmatically registering a factory that is also configured via pipeline options; library code that registers a factory conflicting with user config.","solutions":["Remove the duplicate typeinfo registration so each type has exactly one factory.","If registering programmatically, check registeredTypeInfoFactories or wrap registration to skip if already present.","Audit the serialization-config for repeated typeinfo entries targeting the same class."],"exampleFix":"# before (duplicate typeinfo for same class)\npipeline.serialization-config: \"class:com.example.MyType{type:typeinfo,class:com.example.FooFactory};class:com.example.MyType{type:typeinfo,class:com.example.BarFactory}\"\n\n# after (single factory)\npipeline.serialization-config: \"class:com.example.MyType{type:typeinfo,class:com.example.FooFactory}\"","handlingStrategy":"validation","validationCode":"// Check for existing registration before adding\n// (registerTypeWithTypeInfoFactory does not expose a contains check externally,\n//  so deduplicate at the config/source level)\nSet<Class<?>> seen = new HashSet<>();\nfor (String entry : configEntries) {\n    Class<?> type = parseType(entry);\n    if (!seen.add(type)) {\n        throw new IllegalStateException(\"Duplicate TypeInfoFactory for: \" + type);\n    }\n}","typeGuard":null,"tryCatchPattern":"try {\n    config.registerTypeWithTypeInfoFactory(type, factory);\n} catch (InvalidTypesException e) {\n    if (e.getMessage().contains(\"already registered\")) {\n        // skip or replace existing registration\n    } else {\n        throw e;\n    }\n}","preventionTips":["Ensure each type appears at most once in typeinfo serialization-config entries.","Avoid mixing programmatic factory registration with config-based registration for the same type."],"tags":["serialization","type-information","duplicate","configuration"],"backgroundTag":null,"analyzedSha":"2f3c205e9266cb30240eb7f4fdab15cad629a70f","analyzedAt":"2026-08-14T08:48:24.518Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}