{"record":{"id":"fe45b3ca0c43ce28","repo":"apache/flink","slug":"a-typeinfofactory-for-type-is-already-registe-fe45b3","errorCode":null,"errorMessage":"A TypeInfoFactory for type '{}' is already registered.","messagePattern":"A TypeInfoFactory for type '(.+?)' is already registered\\.","errorType":"exception","errorClass":"InvalidTypesException","httpStatus":null,"severity":"error","filePath":"flink-core/src/main/java/org/apache/flink/api/java/typeutils/TypeExtractor.java","lineNumber":166,"sourceCode":"     * Registers a type information factory globally for a certain type. Every following type\n     * extraction operation will use the provided factory for this type. The factory will have the\n     * highest precedence for this type. In a hierarchy of types the registered factory has higher\n     * precedence than annotations at the same level but lower precedence than factories defined\n     * down the hierarchy.\n     *\n     * @param t type for which a new factory is registered\n     * @param factory type information factory that will produce {@link TypeInformation}\n     */\n    @Internal\n    public static void registerFactory(Type 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    // --------------------------------------------------------------------------------------------\n    //  Function specific methods\n    // --------------------------------------------------------------------------------------------\n\n    @PublicEvolving\n    public static <IN, OUT> TypeInformation<OUT> getMapReturnTypes(\n            MapFunction<IN, OUT> mapInterface, TypeInformation<IN> inType) {\n        return getMapReturnTypes(mapInterface, inType, null, false);\n    }\n\n    @PublicEvolving\n    public static <IN, OUT> TypeInformation<OUT> getMapReturnTypes(\n            MapFunction<IN, OUT> mapInterface,","sourceCodeStart":148,"sourceCodeEnd":184,"githubUrl":"https://github.com/apache/flink/blob/2f3c205e9266cb30240eb7f4fdab15cad629a70f/flink-core/src/main/java/org/apache/flink/api/java/typeutils/TypeExtractor.java#L148-L184","documentation":"Thrown by TypeExtractor.registerFactory when a TypeInfoFactory has already been registered for the given Type. The registration is stored in a static ConcurrentHashMap (registeredTypeInfoFactories) keyed by the Type. Attempting to register a second factory for the same Type is rejected to prevent ambiguous type information resolution.","triggerScenarios":"Calling TypeExtractor.registerFactory(MyType.class, FactoryA.class) and later TypeExtractor.registerFactory(MyType.class, FactoryB.class). The static map persists for the JVM lifetime, so two separate calls in the same process for the same type trigger this.","commonSituations":"Multiple modules or libraries each register a TypeInfoFactory for the same type. Static initialization blocks in different classes both registering factories for a shared type. Unit tests that register factories without cleanup and then run in the same JVM.","solutions":["Consolidate to a single TypeInfoFactory registration per type.","If different factories are needed for the same type in different contexts, use a single factory that dispatches based on runtime conditions.","For tests, run each test in a separate JVM or avoid re-registering the same type.","Check registeredTypeInfoFactories before registering if you suspect a prior registration."],"exampleFix":"// before\nTypeExtractor.registerFactory(MyType.class, FactoryA.class);\n// ... later in another module ...\nTypeExtractor.registerFactory(MyType.class, FactoryB.class); // throws\n// after\n// Register only once, in a shared location:\nTypeExtractor.registerFactory(MyType.class, FactoryA.class);","handlingStrategy":"validation","validationCode":"// Check before registering — there is no public getter, so track in your own code\nif (alreadyRegisteredTypes.contains(t)) {\n    throw new IllegalStateException(\"Factory already registered for \" + t);\n}\nTypeExtractor.registerFactory(t, factory);\nalreadyRegisteredTypes.add(t);","typeGuard":null,"tryCatchPattern":"try {\n    TypeExtractor.registerFactory(type, factory);\n} catch (InvalidTypesException e) {\n    if (e.getMessage().contains(\"already registered\")) {\n        // already registered by another module; acceptable\n        return;\n    }\n    throw e;\n}","preventionTips":["Register each type's factory exactly once, ideally in a static initializer of a shared class.","For tests, use separate JVM forks or avoid re-registering.","Centralize factory registration in a single bootstrap location."],"tags":["type-extraction","typeinfo-factory","registration","duplicate"],"backgroundTag":null,"analyzedSha":"2f3c205e9266cb30240eb7f4fdab15cad629a70f","analyzedAt":"2026-08-14T08:48:24.518Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}