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

  1. Verify with cmmnHistoryService.createHistoricCaseInstanceQuery().caseInstanceId(id).singleResult() that endTime != null before reactivating
  2. Use the correct id: fetch the finished instance via CmmnHistoryService and pass its id to the ReactivationBuilder
  3. If the intent was to influence a running case, use plan item APIs (planItemInstanceQuery/complete/terminate) instead of reactivation
  4. 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

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


AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11). Data as JSON: /api/errors/24b5e06ca5dc708c. Report an issue: GitHub.