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

  1. Ensure the configured TreeBuilder class is concrete with a public no-arg (or Feature[]) constructor
  2. Check the class name in the properties for typos and that the class is on the classpath
  3. 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

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


AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11). Data as JSON: /api/errors/b479c3888ad2d815. Report an issue: GitHub.