flowable/flowable-engine · error · FlowableIllegalStateException
Case instance is still running, cannot reactivate historic c
Error message
Case instance is still running, cannot reactivate historic case instance:
What it means
Thrown as FlowableIllegalStateException by ReactivateHistoricCaseInstanceCmd when the historic case instance looked up by reactivationBuilder.getCaseInstanceId() is still running (its END_TIME_ is null). Reactivation is only defined for completed (historic) case instances, so the engine refuses to reactivate a live one.
Source
Thrown at modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/cmd/ReactivateHistoricCaseInstanceCmd.java:74
}
@Override
public CaseInstance execute(CommandContext commandContext) {
if (reactivationBuilder.getCaseInstanceId() == null) {
throw new FlowableIllegalArgumentException("No historic case instance id provided");
}
// Check if the historic case instance is found and if it is no longer running
CmmnEngineConfiguration cmmnEngineConfiguration = CommandContextUtil.getCmmnEngineConfiguration(commandContext);
HistoricCaseInstance instance = cmmnEngineConfiguration.getHistoricCaseInstanceEntityManager().createHistoricCaseInstanceQuery()
.caseInstanceId(reactivationBuilder.getCaseInstanceId())
.singleResult();
if (instance == null) {
throw new FlowableObjectNotFoundException("No historic case instance to be reactivated found with id: " + reactivationBuilder.getCaseInstanceId(), HistoricCaseInstance.class);
}
if (instance.getEndTime() == null) {
throw new FlowableIllegalStateException("Case instance is still running, cannot reactivate historic case instance: " + reactivationBuilder.getCaseInstanceId());
}
// move the case instance back to the runtime (this also checks, if the reactivation listener is even existent)
CaseInstanceEntity caseInstanceEntity = cmmnEngineConfiguration.getCaseInstanceHelper()
.copyHistoricCaseInstanceToRuntime(instance);
// reset the state to be active again and also set the last reactivation time as well as the current user triggering it
caseInstanceEntity.setState(CaseInstanceState.ACTIVE);
caseInstanceEntity.setLastReactivationTime(cmmnEngineConfiguration.getClock().getCurrentTime());
caseInstanceEntity.setLastReactivationUserId(Authentication.getAuthenticatedUserId());
// set case variables, if the builder contains any
if (reactivationBuilder.hasVariables()) {
caseInstanceEntity.setVariables(reactivationBuilder.getVariables());
}
// set transient case variables, if the builder contains any
if (reactivationBuilder.hasTransientVariables()) {View on GitHub (pinned to d6d39ce1c6)
Solutions
- Verify with cmmnHistoryService.createHistoricCaseInstanceQuery().caseInstanceId(id).singleResult() that endTime != null before reactivating
- Use the correct id: fetch the finished instance via CmmnHistoryService and pass its id to the ReactivationBuilder
- If the intent was to influence a running case, use plan item APIs (planItemInstanceQuery/complete/terminate) instead of reactivation
- Close out the running case (terminate or complete it) first, then reactivate
Example fix
// before
runtimeService.createCaseInstanceReactivationBuilder()
.caseInstanceId(anyInstanceId)
.reactivate();
// after
HistoricCaseInstance h = cmmnHistoryService.createHistoricCaseInstanceQuery()
.caseInstanceId(anyInstanceId).singleResult();
if (h != null && h.getEndTime() != null) {
runtimeService.createCaseInstanceReactivationBuilder()
.caseInstanceId(h.getId())
.reactivate();
} Defensive patterns
Strategy: validation
Validate before calling
HistoricCaseInstance h = cmmnHistoryService.createHistoricCaseInstanceQuery()
.caseInstanceId(id).singleResult();
if (h == null) throw new IllegalArgumentException("no historic case instance " + id);
if (h.getEndTime() == null) throw new IllegalStateException("case instance still running: " + id); Try / catch
try { runtimeService.createCaseInstanceReactivationBuilder().caseInstanceId(id).reactivate(); }
catch (FlowableIllegalStateException e) { /* case still running — resolve runtime instance instead */ } Prevention
- Always resolve the id via HistoricCaseInstanceQuery and confirm endTime is set
- Distinguish runtime ids from historic ids in your code paths
- Document that reactivation is only for completed cases
When it happens
Trigger: Calling CaseInstanceStateManager/CmmnRuntimeService.reactivateCaseInstance(reactivationBuilder) with a caseInstanceId that refers to a case instance that is still active in the runtime tables rather than one that has ended.
Common situations: Passing a runtime case instance id instead of a historic one (ids are shared in Flowable); re-running a reactivation script against a case that was never completed; a race where the case completes after the caller checked.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- Could not find reactivation listener plan item instance in c
- Can only complete a case instance which is marked as complet
- There can only be one reactivation listener on a case model,
- Could not find plan item instance for plan item with definit
- Cannot exit case with 'complete' event type as the case '${c
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/24b5e06ca5dc708c.
Report an issue: GitHub.