flowable/flowable-engine · error · ParseException

' + token.getImage() + '

Error message

' + token.getImage() + '

What it means

Parser.fail(String expected) throws a ParseException positioned at the current token, with a message built from the unexpected token image wrapped in single quotes and the expected construct. It is the parser's generic 'I found token X where I expected Y' failure for literal/number parsing, lambda-parameter extraction, and token consumption.

Source

Thrown at modules/flowable-engine-common/src/main/java/org/flowable/common/engine/impl/de/odysseus/el/tree/impl/Parser.java:416

	}

	protected final List<FunctionNode> getFunctions() {
		return functions;
	}
	
	protected final List<IdentifierNode> getIdentifiers() {
		return identifiers;
	}

	protected final Token getToken() {
		return token;
	}

	/**
	 * throw exception
	 */
	protected void fail(String expected) throws ParseException {
		throw new ParseException(position, "'" + token.getImage() + "'", expected);
	}

	/**
	 * throw exception
	 */
	protected void fail(Symbol expected) throws ParseException {
		fail(expected.toString());
	}

	/**
	 * get lookahead symbol.
	 */
	protected final Token lookahead(int index) throws ScanException, ParseException {
		if (lookahead.isEmpty()) {
			lookahead = new LinkedList<>();
		}
		while (index >= lookahead.size()) {
			lookahead.add(new LookaheadToken(scanner.next(), scanner.getPosition()));

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Read ParseException.getPosition(), getEncountered() and getExpected() to see exactly which token was rejected and what was expected.
  2. Fix the expression at the reported position (remove/replace the unexpected token).
  3. Validate expressions at startup/deployment rather than at evaluation time.
  4. Check lambda expressions against the library's supported syntax (identifier list before '->').

Example fix

// before
String expr = "${list->x > 2}"; // bad lambda syntax
// after
String expr = "${(x -> x > 2)(list)}";
Defensive patterns

Strategy: validation

Validate before calling

// parse-check expression before use
try {
    builder.build(expr);
} catch (TreeBuilderException e) {
    throw new IllegalArgumentException("Token error at " + e.getPosition() + ": expected " + e.getExpected());
}

Try / catch

try {
    return builder.build(expr);
} catch (TreeBuilderException e) {
    throw new IllegalArgumentException("Unexpected token '" + e.getEncountered() + "' at " + e.getPosition() + ", expected " + e.getExpected());
}

Prevention

When it happens

Trigger: Parsing an expression where a token appears in an illegal place: a non-integer where an integer literal is required (parseInteger), a non-number where a float is required (parseFloat), a malformed lambda parameter list (extractLambdaParameters), or any unexpected token during tree construction (consumeToken).

Common situations: Typos in EL expressions such as '${123abc}' or '${fn(,a)}'; malformed lambda syntax like '${x-> }'; copy-pasted expressions from other EL dialects (JSF/JSP vs Flowable) with unsupported syntax.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


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