flowable/flowable-engine · error · FlowableException
HitPolicy: %s has aggregation: %s needs output type number
Error message
HitPolicy: %s has aggregation: %s needs output type number
What it means
A COLLECT hit policy with an aggregation must aggregate over a single output whose type is 'number'. The sanity check rejects tables whose sole output column declares a different typeRef because the aggregator result would be untyped or wrong.
Source
Thrown at modules/flowable-dmn-engine/src/main/java/org/flowable/dmn/engine/impl/RuleEngineExecutorImpl.java:329
if (hitPolicyBehavior == null) {
String hitPolicyBehaviorNotFoundMessage = String.format("HitPolicy behavior: %s not configured", hitPolicy.getValue());
LOGGER.error(hitPolicyBehaviorNotFoundMessage);
throw new FlowableException(hitPolicyBehaviorNotFoundMessage);
}
return hitPolicyBehavior;
}
protected void sanityCheckDecisionTable(DecisionTable decisionTable) {
if (decisionTable.getHitPolicy() == HitPolicy.COLLECT && decisionTable.getAggregation() != null && decisionTable.getOutputs() != null) {
if (decisionTable.getOutputs().size() > 1) {
throw new FlowableException(String.format("HitPolicy: %s has aggregation: %s and multiple outputs. This is not supported", decisionTable.getHitPolicy(), decisionTable.getAggregation()));
}
if (!"number".equals(decisionTable.getOutputs().get(0).getTypeRef())) {
throw new FlowableException(String.format("HitPolicy: %s has aggregation: %s needs output type number", decisionTable.getHitPolicy(), decisionTable.getAggregation()));
}
}
}
@Override
public Map<String, AbstractHitPolicy> getHitPolicyBehaviors() {
return hitPolicyBehaviors;
}
@Override
public void setHitPolicyBehaviors(Map<String, AbstractHitPolicy> hitPolicyBehaviors) {
this.hitPolicyBehaviors = hitPolicyBehaviors;
}
@Override
public ExpressionManager getExpressionManager() {
return expressionManager;
}View on GitHub (pinned to d6d39ce1c6)
Solutions
- Set the output column typeRef to "number" in the DMN XML
- If the aggregated value is not numeric, remove the aggregation or change the hit policy
- Re-validate/redeploy the corrected decision table
Example fix
// before <outputEntry typeRef="string">...</outputEntry> // after <outputEntry typeRef="number">...</outputEntry>
Defensive patterns
Strategy: validation
Validate before calling
if (dt.getHitPolicy() == HitPolicy.COLLECT && dt.getAggregation() != null && dt.getOutputs() != null && dt.getOutputs().size() == 1) {
if (!"number".equals(dt.getOutputs().get(0).getTypeRef())) throw new IllegalArgumentException("aggregation output must be number");
} Prevention
- Always set typeRef="number" on aggregated output columns
- Lint DMN XML for aggregation/typeRef consistency in CI
When it happens
Trigger: execute -> sanityCheckDecisionTable finds COLLECT + aggregation, one output, and its typeRef is not "number" (e.g. string, boolean, date).
Common situations: Authoring mistake in the DMN editor where the output column type was left as string or not set; tables converted from tools that don't enforce numeric aggregation.
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
- more than one result in decision:
- more than one result
- HitPolicy behavior: %s not configured
- HitPolicy: %s has aggregation: %s and multiple outputs. This
- decision table does not contain a hit policy
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/48e83e30a913dcf7.
Report an issue: GitHub.