flowable/flowable-engine · error · NullPointerException

resolver must not be null

Error message

resolver must not be null

What it means

Null-component guard in CompositeELResolver.add: an attempt was made to add a null ELResolver to the composite chain. Since resolvers are consulted in order, a null entry would break EL evaluation, so it is rejected with a NullPointerException per the Javadoc contract.

Solutions

  1. Register only non-null ELResolver instances
  2. Check resolver construction/injection before adding to the composite

Example fix

// before
composite.add(customResolver); // may be null
// after
if (customResolver != null) { composite.add(customResolver); }
Defensive patterns

Strategy: validation

Validate before calling

if (resolver == null) { throw new IllegalStateException("EL resolver not configured"); } composite.add(resolver);

Type guard

void addIfPresent(CompositeELResolver composite, ELResolver r) { if (r != null) composite.add(r); }

Try / catch

try { composite.add(resolver); } catch (NullPointerException e) { /* resolver construction failed upstream */ }

Prevention

When it happens

Trigger: Programmatically building an EL resolver chain (e.g. in createElResolver / ProcessEngineConfiguration EL resolver setup) and adding a resolver variable that is null — typically an unregistered custom resolver bean or a factory method returning null.

Common situations: Flowable engine configuration where a custom EL resolver is conditionally created but returns null; DI wiring where the resolver bean is absent; ordering of initialization before the resolver is constructed.

Related errors


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

Appendix: source

Thrown at modules/flowable-engine-common/src/main/java/org/flowable/common/engine/impl/javax/el/CompositeELResolver.java:44

	}

	public CompositeELResolver(Collection<ELResolver> resolvers) {
		this.resolvers.addAll(resolvers);
	}

	/**
	 * Adds the given resolver to the list of component resolvers. Resolvers are consulted in the
	 * order in which they are added.
	 * 
	 * @param elResolver
	 *            The component resolver to add.
	 * @throws NullPointerException
	 *             If the provided resolver is null.
	 */
	public void add(ELResolver elResolver) {
		if (elResolver == null) {
			throw new NullPointerException("resolver must not be null");
		}
		resolvers.add(elResolver);
	}

	/**
	 * Returns the most general type that this resolver accepts for the property argument, given a
	 * base object. One use for this method is to assist tools in auto-completion. The result is
	 * obtained by querying all component resolvers. The Class returned is the most specific class
	 * that is a common superclass of all the classes returned by each component resolver's
	 * getCommonPropertyType method. If null is returned by a resolver, it is skipped.
	 * 
	 * @param context
	 *            The context of this evaluation.
	 * @param base
	 *            The base object to return the most general property type for, or null to enumerate
	 *            the set of top-level variables that this resolver can evaluate.
	 * @return null if this ELResolver does not know how to handle the given base object; otherwise
	 *         Object.class if any type of property is accepted; otherwise the most general property

View on GitHub (pinned to d6d39ce1c6)