flowable/flowable-engine · error · FlowableIllegalArgumentException
version must be positive
Error message
version must be positive
What it means
DecisionQueryImpl.checkVersion(Integer) throws FlowableIllegalArgumentException("version must be positive") when a version filter method receives an Integer <= 0. DMN decision versions start at 1, so 0 or negative numbers can never match and are treated as invalid input, rejected before the query executes.
Source
Thrown at modules/flowable-dmn-engine/src/main/java/org/flowable/dmn/engine/impl/DecisionQueryImpl.java:232
@Override
public DmnDecisionQuery decisionVersionLowerThan(Integer decisionVersion) {
checkVersion(decisionVersion);
this.versionLt = decisionVersion;
return this;
}
@Override
public DmnDecisionQuery decisionVersionLowerThanOrEquals(Integer decisionVersion) {
checkVersion(decisionVersion);
this.versionLte = decisionVersion;
return this;
}
protected void checkVersion(Integer version) {
if (version == null) {
throw new FlowableIllegalArgumentException("version is null");
} else if (version <= 0) {
throw new FlowableIllegalArgumentException("version must be positive");
}
}
@Override
public DecisionQueryImpl latestVersion() {
this.latest = true;
return this;
}
@Override
public DmnDecisionQuery decisionTenantId(String tenantId) {
if (tenantId == null) {
throw new FlowableIllegalArgumentException("decision tenantId is null");
}
this.tenantId = tenantId;
return this;
}
View on GitHub (pinned to d6d39ce1c6)
Solutions
- Pass a version >= 1; add an input check like `if (version < 1) throw ...` before calling the query.
- If version is unknown/unset, avoid the version filter entirely or use latestVersion().
- Check the numbering convention of the upstream source and add +1 offsets if it starts at 0.
Example fix
// before
int version = 0; // default
query.decisionVersion(version);
// after
if (version >= 1) {
query.decisionVersion(version);
} else {
query.latestVersion();
} Defensive patterns
Strategy: validation
Validate before calling
if (version != null && version >= 1) {
query.decisionVersion(version);
} else {
query.latestVersion();
} Type guard
boolean isValidVersion(Integer v) { return v != null && v > 0; } Try / catch
try {
query.decisionVersion(version);
} catch (FlowableIllegalArgumentException e) {
if (e.getMessage() != null && e.getMessage().contains("positive")) {
query.latestVersion();
} else { throw e; }
} Prevention
- Remember DMN versions are 1-based
- Replace `int version = 0` sentinels with Optional<Integer>
- Clamp or reject versions < 1 at input parsing time
When it happens
Trigger: Calling decisionVersion(0), decisionVersion(-1), decisionVersionGreaterThan(0), etc. — typically versions initialized to 0 as a sentinel, off-by-one arithmetic, or unvalidated user input.
Common situations: Defaults like `int version = 0;` that are never overwritten when config/lookup fails; loop arithmetic or subtraction yielding 0/negative; external systems that report versions starting at 0 while Flowable starts at 1.
Understand the failure class
Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.
Related errors
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/70f591bfcb5c67c6.
Report an issue: GitHub.