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

  1. 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
  2. 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)
  3. Check the wrapped cause in the exception for the real failure (e.g. ClassNotFoundException, InvocationTargetException) and fix the missing dependency or throwing init code
  4. 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

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


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)