flowable/flowable-engine · error · ELException
TypeConverter ${clazz} could not be instantiated
Error message
TypeConverter ${clazz} could not be instantiated What it means
createTypeConverter() instantiates the TypeConverter implementation named by the PROP_TYPE_CONVERTER property via reflection (clazz.newInstance()). Any failure — no public no-arg constructor, abstract class, wrong type, or constructor exception — is wrapped as ELException 'TypeConverter X could not be instantiated'.
Source
Thrown at modules/flowable-engine-common/src/main/java/org/flowable/common/engine/impl/de/odysseus/el/ExpressionFactoryImpl.java:372
return new TreeStore(builder, cache);
}
/**
* Create the factory's type converter. This implementation takes the
* <code>de.odysseus.el.misc.TypeConverter</code> property as the name of a class implementing
* the <code>de.odysseus.el.misc.TypeConverter</code> interface. If the property is not set, the
* default converter (<code>TypeConverter.DEFAULT</code>) is used.
*/
protected TypeConverter createTypeConverter(Properties properties) {
Class<?> clazz = load(TypeConverter.class, properties);
if (clazz == null) {
return TypeConverter.DEFAULT;
}
try {
return TypeConverter.class.cast(clazz.newInstance());
} catch (Exception e) {
throw new ELException("TypeConverter " + clazz + " could not be instantiated", e);
}
}
/**
* Create the factory's builder. This implementation takes the
* <code>de.odysseus.el.tree.TreeBuilder</code> property as a name of a class implementing the
* <code>de.odysseus.el.tree.TreeBuilder</code> interface. If the property is not set, a plain
* <code>de.odysseus.el.tree.impl.Builder</code> is used. If the configured class is a subclass
* of <code>de.odysseus.el.tree.impl.Builder</code> and which provides a constructor taking an
* array of <code>Builder.Feature</code>, this constructor will be invoked. Otherwise, the
* default constructor will be used.
*/
protected TreeBuilder createTreeBuilder(Properties properties, Feature... features) {
Class<?> clazz = load(TreeBuilder.class, properties);
if (clazz == null) {
return createDefaultTreeBuilder(features);
}
try {View on GitHub (pinned to d6d39ce1c6)
Solutions
- Give the configured TypeConverter implementation a public no-argument constructor
- Verify the class extends/implements TypeConverter (so the cast succeeds)
- Confirm the class is concrete (not abstract/interface) and its constructor does not throw
- Remove the property to use TypeConverter.DEFAULT
Example fix
// before
public class MyConverter extends TypeConverterImpl {
public MyConverter(String locale) { ... }
}
// after
public class MyConverter extends TypeConverterImpl {
public MyConverter() { ... }
} Defensive patterns
Strategy: validation
Validate before calling
Class<?> c = Class.forName("com.acme.MyConverter");
if (!org.flowable.common.engine.impl.de.odysseus.el.TypeConverter.class.isAssignableFrom(c)
|| java.lang.reflect.Modifier.isAbstract(c.getModifiers())
|| c.getConstructors().length == 0 || java.util.Arrays.stream(c.getConstructors()).noneMatch(k -> k.getParameterCount() == 0)) {
throw new IllegalStateException("TypeConverter must be concrete with a public no-arg constructor");
} Try / catch
try {
ExpressionFactory factory = new ExpressionFactoryImpl(props);
} catch (ELException e) {
if (e.getMessage().contains("TypeConverter") && e.getMessage().contains("could not be instantiated")) {
log.error("Check constructor/TypeConverter contract of configured class", e);
}
throw e;
} Prevention
- Give custom converters a public no-arg constructor
- Keep converters free of environment-dependent constructor logic
- Add a reflective contract test for any class named in engine properties
When it happens
Trigger: ExpressionFactoryImpl construction with a TypeConverter property naming a class that lacks a public no-arg constructor, is abstract/interface, throws in its constructor, or does not extend TypeConverter (then ClassCastException in cast).
Common situations: Pointing the property at a custom converter with only parameterized constructors; typo causing the wrong class to be named; converter class present but initializing state in constructor that fails (e.g. missing Spring context).
Related errors
- TreeBuilder ${clazz} could not be instantiated
- Builder ${clazz} is missing constructor (can't pass features
- Class ${className} not found
- Cannot read EL properties
- Cannot parse EL property ${PROP_CACHE_SIZE}
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/adb5e9d503a1d3a9.
Report an issue: GitHub.