nathanmarz/storm · error · IllegalArgumentException
Unable to create serializer
Error message
Unable to create serializer "${serializerClass.getName()}" for class: ${superClass.getName()} What it means
SerializationFactory.resolveSerializerInstance instantiates a Kryo serializer class registered for a type. When Class.newInstance() (or equivalent) throws any Exception, it is wrapped in this IllegalArgumentException, naming the serializer class and the class it was meant to serialize. It means the registered serializer class cannot be instantiated — typically no public no-arg constructor, a constructor that throws, or wrong type (not a Serializer subclass for that class).
Solutions
- Give the serializer class a public no-arg constructor, or register an Instance/SerializerFactory (Kryo.register(cls, new InstanceSerializer(...)/new SerializerFactory)) instead of the raw class
- Make sure the serializer class extends the expected Kryo Serializer for the registered class and is public, non-abstract, and static (not a non-static inner class)
- Check the wrapped cause in the exception for the real failure (e.g. ClassNotFoundException, InvocationTargetException) and fix the missing dependency or throwing init code
- Ensure the topology jar actually contains the serializer class and its dependencies (shade/assembly plugin includes it)
Example fix
// before
public class MySerializer extends Serializer<MyType> {
public MySerializer(String param) { ... } // no no-arg ctor
}
conf.registerSerialization(MyType.class, MySerializer.class);
// after
public class MySerializer extends Serializer<MyType> {
public MySerializer() { } // public no-arg constructor
}
conf.registerSerialization(MyType.class, MySerializer.class); Defensive patterns
Strategy: validation
Validate before calling
// before submitting topology, for each registered serializer:
Class<?> ser = Class.forName(serializerClassName);
if (java.lang.reflect.Modifier.isAbstract(ser.getModifiers()))
throw new IllegalStateException(ser + " is abstract");
ser.getDeclaredConstructor(); // fails fast if no no-arg ctor
if (!com.esotericsoftware.kryo.Serializer.class.isAssignableFrom(ser))
throw new IllegalStateException(ser + " is not a Kryo Serializer"); Try / catch
try {
launchTopology(conf);
} catch (IllegalArgumentException e) {
if (e.getMessage() != null && e.getMessage().startsWith("Unable to create serializer")) {
// inspect e.getCause() for the real instantiation failure
}
throw e;
} Prevention
- Always give custom Kryo serializers a public no-arg constructor
- Test serializer registration in local mode (LocalCluster) before cluster deploy
- Register via Kryo's SerializerFactory/Instance when the serializer needs constructor args
- Shade all serializer dependencies into the topology jar
When it happens
Trigger: Registering a serializer class via Config.TOPOLOGY_KRYO_REGISTER (or topology.kryo.register) whose class has no public no-arg constructor, whose constructor throws, that is abstract, or whose static initializer fails; Kryo calls newInstance during getKryo/serializer resolution at topology startup.
Common situations: Custom serializers written without a no-arg constructor; serializers requiring constructor arguments (Kryo needs Class-based instantiation); class present in jar but missing dependencies so its static init or constructor throws ClassNotFound/NoClassDefFound; packaging a serializer from a different Kryo version.
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.
Related errors
- Cannot set serializations for a component using fluent API
- Could not instantiate a class listed in config under section
- Blowfish encryption key not specified
- Blowfish encryption key invalid
- Don't know how to convert
AI-assisted analysis of nathanmarz/storm@cdb116e942 (2026-09-12).
Data as JSON: /api/errors/36cc51f151ddc2ed.
Report an issue: GitHub.
Appendix: source
Thrown at storm-core/src/jvm/backtype/storm/serialization/SerializationFactory.java:197
} catch (Exception ex3) {
try {
return serializerClass.getConstructor(Kryo.class).newInstance(k);
} catch (Exception ex4) {
try {
return serializerClass.getConstructor(Class.class, Map.class).newInstance(superClass, conf);
} catch (Exception ex5) {
try {
return serializerClass.getConstructor(Class.class).newInstance(superClass);
} catch (Exception ex6) {
return serializerClass.newInstance();
}
}
}
}
}
}
} catch (Exception ex) {
throw new IllegalArgumentException("Unable to create serializer \""
+ serializerClass.getName()
+ "\" for class: "
+ superClass.getName(), ex);
}
}
private static Map<String, String> normalizeKryoRegister(Map conf) {
// TODO: de-duplicate this logic with the code in nimbus
Object res = conf.get(Config.TOPOLOGY_KRYO_REGISTER);
if(res==null) return new TreeMap<String, String>();
Map<String, String> ret = new HashMap<String, String>();
if(res instanceof Map) {
ret = (Map<String, String>) res;
} else {
for(Object o: (List) res) {
if(o instanceof Map) {
ret.putAll((Map) o);
} else {View on GitHub (pinned to cdb116e942)