flowable/flowable-engine · error · IllegalStateException
The [ ] must resolve to an Number or a String that can be…
Error message
The [<attribute>] must resolve to an Number or a String that can be parsed as a Double. Resolved to [<class>] for [<value>]
What it means
resolveExpressionAsDouble resolves an attribute expression expecting a Double, Double-parseable String, or null; anything else throws IllegalStateException. It backs the retry backoff multiplier, so a wrongly typed multiplier expression triggers this during endpoint creation.
Solutions
- Set multiplier to a numeric value or numeric String with a decimal point, e.g. 2.0 or "2.0".
- Fix the referenced property so it is a Double, not a collection/boolean.
- Check the expression/placeholder key for typos resolving to an unrelated bean.
- Use a dot as decimal separator; avoid locale-formatted strings.
Example fix
// before
flowable:
kafka:
retry:
multiplier: [2.0, 3.0] # resolves to a List
// after
flowable:
kafka:
retry:
multiplier: 2.0 Defensive patterns
Strategy: type-guard
Validate before calling
Object v = resolveExpression(value); if (v != null && !(v instanceof Number) && !(v instanceof String)) throw new IllegalArgumentException(attribute + " must be double-like");
Type guard
boolean isDoubleLike(Object v) { return v == null || v instanceof Number || (v instanceof String s && s.matches("-?\\d+(\\.\\d+)?")); } Try / catch
try { ... } catch (IllegalStateException e) { if (e.getMessage().contains("parsed as a Double")) { log.error("Backoff multiplier not a Double: {}", e.getMessage()); } else throw e; } Prevention
- Configure multiplier as a single decimal number (e.g. 2.0)
- Never bind multiplier to lists or flags
- Use dot decimal separator regardless of locale
When it happens
Trigger: The multiplier attribute of the retry backoff configuration resolves to a type that is neither Number, String, nor null (e.g. Boolean, List) when resolveRetryConfiguration builds the retry template.
Common situations: Multiplier bound to a boolean flag by mistake; placeholder points at a list of multipliers instead of a single value; locale-formatted decimal string like "1,5" fails parse (NumberFormatException) vs wrong class here is object type mismatch.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- The [ ] must resolve to an Number or a String that can be…
- Channel definition cannot resolve as a String[] or a String
- expected expression to resolve to but it did not. Resolved…
- partition in TopicPartition for topic
- The [ ] must resolve to a Boolean or a String that can be…
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/faad1908fe8c3131.
Report an issue: GitHub.
Appendix: source
Thrown at modules/flowable-event-registry-spring/src/main/java/org/flowable/eventregistry/spring/kafka/KafkaChannelDefinitionProcessor.java:492
} else if (resolved instanceof Number) {
result = ((Number) resolved).longValue();
} else if (resolved != null) {
throw new IllegalStateException(
"The [" + attribute + "] must resolve to an Number or a String that can be parsed as a Long. "
+ "Resolved to [" + resolved.getClass() + "] for [" + value + "]");
}
return result;
}
protected Double resolveExpressionAsDouble(String value, String attribute) {
Object resolved = resolveExpression(value);
Double result = null;
if (resolved instanceof String) {
result = Double.parseDouble((String) resolved);
} else if (resolved instanceof Number) {
result = ((Number) resolved).doubleValue();
} else if (resolved != null) {
throw new IllegalStateException(
"The [" + attribute + "] must resolve to an Number or a String that can be parsed as a Double. "
+ "Resolved to [" + resolved.getClass() + "] for [" + value + "]");
}
return result;
}
protected Boolean resolveExpressionAsBoolean(String value, String attribute) {
return resolveExpressionAsBoolean(value, attribute, null);
}
protected Boolean resolveExpressionAsBoolean(String value, String attribute, Boolean defaultValue) {
Object resolved = resolveExpression(value);
Boolean result = defaultValue;
if (resolved instanceof String) {
result = Boolean.parseBoolean((String) resolved);
} else if (resolved instanceof Boolean) {
result = (Boolean) resolved;
} else if (resolved != null) {View on GitHub (pinned to d6d39ce1c6)