apache/flink · error · InvalidTypesException
A TypeInfoFactory for type '{}' is already registered.
Error message
A TypeInfoFactory for type '{}' is already registered. What it means
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.
Source
Thrown at flink-core/src/main/java/org/apache/flink/api/common/serialization/SerializerConfigImpl.java:478
loadClass(m.get("class"), classLoader, "Could not load TypeInfoFactory's class");
// Register in the global static factory map of TypeExtractor for now so that it can be
// accessed from the static methods of TypeExtractor where SerializerConfig is currently
// not accessible
TypeExtractor.registerFactory(t, factoryClass);
// Register inside SerializerConfig only for testing purpose for now
registerTypeWithTypeInfoFactory(t, factoryClass);
}
private void registerTypeWithTypeInfoFactory(
Class<?> t, Class<? extends TypeInfoFactory<?>> factory) {
Preconditions.checkNotNull(t, "Type parameter must not be null.");
Preconditions.checkNotNull(factory, "Factory parameter must not be null.");
if (!TypeInfoFactory.class.isAssignableFrom(factory)) {
throw new IllegalArgumentException("Class is not a TypeInfoFactory.");
}
if (registeredTypeInfoFactories.containsKey(t)) {
throw new InvalidTypesException(
"A TypeInfoFactory for type '" + t + "' is already registered.");
}
registeredTypeInfoFactories.put(t, factory);
}
@Override
public SerializerConfigImpl copy() {
final SerializerConfigImpl newSerializerConfig = new SerializerConfigImpl();
newSerializerConfig.configure(configuration, this.getClass().getClassLoader());
getRegisteredTypesWithKryoSerializers()
.forEach(
(c, s) ->
newSerializerConfig.registerTypeWithKryoSerializer(
c, s.getSerializer()));
getRegisteredTypesWithKryoSerializerClasses()
.forEach(newSerializerConfig::registerTypeWithKryoSerializer);
getDefaultKryoSerializers()View on GitHub (pinned to 2f3c205e92)
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.
Example fix
# before (duplicate typeinfo for same class)
pipeline.serialization-config: "class:com.example.MyType{type:typeinfo,class:com.example.FooFactory};class:com.example.MyType{type:typeinfo,class:com.example.BarFactory}"
# after (single factory)
pipeline.serialization-config: "class:com.example.MyType{type:typeinfo,class:com.example.FooFactory}" Defensive patterns
Strategy: validation
Validate before calling
// Check for existing registration before adding
// (registerTypeWithTypeInfoFactory does not expose a contains check externally,
// so deduplicate at the config/source level)
Set<Class<?>> seen = new HashSet<>();
for (String entry : configEntries) {
Class<?> type = parseType(entry);
if (!seen.add(type)) {
throw new IllegalStateException("Duplicate TypeInfoFactory for: " + type);
}
} Try / catch
try {
config.registerTypeWithTypeInfoFactory(type, factory);
} catch (InvalidTypesException e) {
if (e.getMessage().contains("already registered")) {
// skip or replace existing registration
} else {
throw e;
}
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Duplicated serializer for the same class.
- Serializing the source elements failed: {e.getMessage()}
- {e.getMessage()}
- The implementation of AbstractDeserializationSchema is using
- Cannot register null class or serializer.
AI-assisted analysis of apache/flink@2f3c205e92 (2026-08-14).
Data as JSON: /api/errors/0cf645dd986edf92.
Report an issue: GitHub.