flowable/flowable-engine · error · ELException
TreeBuilder ${clazz} could not be instantiated
Error message
TreeBuilder ${clazz} could not be instantiated What it means
createTreeBuilder() instantiates the configured TreeBuilder class reflectively at the end of its dispatch (either via the Feature[] constructor or clazz.newInstance()). Any reflection failure (instantiation exception, access violation, etc.) is wrapped as ELException 'TreeBuilder 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:406
return createDefaultTreeBuilder(features);
}
try {
if (Builder.class.isAssignableFrom(clazz)) {
Constructor<?> constructor = clazz.getConstructor(Feature[].class);
if (constructor == null) {
if (features == null || features.length == 0) {
return TreeBuilder.class.cast(clazz.newInstance());
} else {
throw new ELException("Builder " + clazz + " is missing constructor (can't pass features)");
}
} else {
return TreeBuilder.class.cast(constructor.newInstance((Object) features));
}
} else {
return TreeBuilder.class.cast(clazz.newInstance());
}
} catch (Exception e) {
throw new ELException("TreeBuilder " + clazz + " could not be instantiated", e);
}
}
protected TreeBuilder createDefaultTreeBuilder(Feature... features) {
return new Builder(features);
}
private Class<?> load(Class<?> clazz, Properties properties) {
if (properties != null) {
String className = properties.getProperty(clazz.getName());
if (className != null) {
ClassLoader loader;
try {
loader = Thread.currentThread().getContextClassLoader();
} catch (Exception e) {
throw new ELException("Could not get context class loader", e);
}
try {View on GitHub (pinned to d6d39ce1c6)
Solutions
- Ensure the configured TreeBuilder class is concrete with a public no-arg (or Feature[]) constructor
- Check the class name in the properties for typos and that the class is on the classpath
- Remove the tree-builder property to use the default Builder
Example fix
// before
props.setProperty("de.odysseus.el.TreeBuilder", "com.acme.MyTreeBuilder"); // abstract
// after
props.setProperty("de.odysseus.el.TreeBuilder", "com.acme.ConcreteTreeBuilder"); Defensive patterns
Strategy: validation
Validate before calling
String name = props.getProperty("de.odysseus.el.TreeBuilder");
if (name != null) {
Class<?> c = Class.forName(name);
if (c.isInterface() || Modifier.isAbstract(c.getModifiers())) {
throw new IllegalStateException("TreeBuilder must be a concrete class: " + name);
}
} Try / catch
try {
ExpressionFactory factory = new ExpressionFactoryImpl(props);
} catch (ELException e) {
if (e.getMessage().contains("TreeBuilder") && e.getMessage().contains("could not be instantiated")) {
log.error("Cannot instantiate configured TreeBuilder: check class and constructors", e);
}
throw e;
} Prevention
- Keep TreeBuilder property values in sync with the codebase (rename refactors)
- Use the default Builder unless a custom one is truly required
- Cover factory construction in an integration smoke test
When it happens
Trigger: ExpressionFactoryImpl creation with PROP_TREE_BUILDER naming a class that cannot be instantiated: no accessible no-arg constructor, abstract class, constructor throws, or security/visibility restrictions.
Common situations: Typo or wrong class name in the tree-builder property; custom builder with required constructor arguments; builder class failing in static/instance initialization due to missing dependencies.
Related errors
- TypeConverter ${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/b479c3888ad2d815.
Report an issue: GitHub.