flowable/flowable-engine · error · FlowableException

Process definition version must be a positive number

Error message

Process definition version must be a positive number

What it means

When no target process definition ID is set, build() validates that the optional migrateToProcessDefinitionVersion is a positive number. A negative version value is invalid because process definition versions start at 1, so build() throws this FlowableException.

Solutions

  1. Pass a positive version number (>= 1) to migrateToProcessDefinition(version, key)
  2. Use 1 or omit the version (migrateToProcessDefinitionKey) if you intend the first/latest version
  3. Validate or sanitize the version value before building the document

Example fix

// before
builder.migrateToProcessDefinition(-1, "orderProcess");
// after
int version = Math.max(1, configuredVersion);
builder.migrateToProcessDefinition(version, "orderProcess");
Defensive patterns

Strategy: validation

Validate before calling

if (targetVersion != null && targetVersion < 1) {
    throw new IllegalArgumentException("Process definition version must be >= 1");
}

Type guard

boolean isValidVersion(Integer v) { return v == null || v >= 1; }

Try / catch

try {
    document = builder.build();
} catch (FlowableException e) {
    if (e.getMessage().contains("must be a positive number")) {
        builder.migrateToProcessDefinitionKey(key); // drop invalid version
        document = builder.build();
    } else { throw e; }
}

Prevention

When it happens

Trigger: Calling build() with migrateToProcessDefinitionId null and migrateToProcessDefinitionVersion set to a negative number, typically via migrateToProcessDefinition(version, key) or a JSON document with a negative version field.

Common situations: Passing a sentinel value like -1 for 'latest version'; parsing a version from config/JSON that was never sanitized; off-by-one or unsigned/signed confusion when computing versions.

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/ff6c189e0bbb66cb. Report an issue: GitHub.

Appendix: source

Thrown at modules/flowable-engine/src/main/java/org/flowable/engine/impl/migration/ProcessInstanceMigrationDocumentBuilderImpl.java:156

        this.processInstanceVariables.put(variableName, variableValue);
        return this;
    }

    @Override
    public ProcessInstanceMigrationDocumentBuilder addProcessInstanceVariables(Map<String, Object> processInstanceVariables) {
        this.processInstanceVariables.putAll(processInstanceVariables);
        return this;
    }

    @Override
    public ProcessInstanceMigrationDocument build() {

        if (migrateToProcessDefinitionId == null) {
            if (migrateToProcessDefinitionKey == null) {
                throw new FlowableException("Process definition key cannot be null");
            }
            if (migrateToProcessDefinitionVersion != null && migrateToProcessDefinitionVersion < 0) {
                throw new FlowableException("Process definition version must be a positive number");
            }
        }

        ProcessInstanceMigrationDocumentImpl document = new ProcessInstanceMigrationDocumentImpl();
        document.setProcessInstanceIdsToMigrate(processInstanceIdsToMigrate);
        document.setMigrateToProcessDefinitionId(migrateToProcessDefinitionId);
        document.setMigrateToProcessDefinition(migrateToProcessDefinitionKey, migrateToProcessDefinitionVersion, migrateToProcessDefinitionTenantId);
        if (preUpgradeScript != null) {
            document.setPreUpgradeScript(preUpgradeScript);
        }
        if (preUpgradeJavaDelegate != null) {
            document.setPreUpgradeJavaDelegate(preUpgradeJavaDelegate);
        }
        if (preUpgradeJavaDelegateExpression != null) {
            document.setPreUpgradeJavaDelegateExpression(preUpgradeJavaDelegateExpression);
        }
        if (postUpgradeScript != null) {
            document.setPostUpgradeScript(postUpgradeScript);

View on GitHub (pinned to d6d39ce1c6)