flowable/flowable-engine · error · FlowableException

Plan item instance for {eventSubscription} can not be found

Error message

Plan item instance for {eventSubscription} can not be found with sub scope id {subScopeId}

What it means

Thrown by DefaultCaseInstanceService.handleSignalEvent when a CMMN event subscription points to a sub scope id for which no plan item instance exists in the runtime data. The engine cannot deliver the signal/trigger to a plan item that has disappeared, so it fails fast with FlowableException instead of silently dropping the event.

Source

Thrown at modules/flowable-cmmn-engine-configurator/src/main/java/org/flowable/cmmn/engine/configurator/impl/cmmn/DefaultCaseInstanceService.java:103

        }

        CaseInstance caseInstance = caseInstanceBuilder.start();
        return caseInstance.getId();
    }

    @Override
    public void handleSignalEvent(EventSubscriptionEntity eventSubscription, Map<String, Object> variables) {
        if (StringUtils.isEmpty(eventSubscription.getSubScopeId())) {
            throw new FlowableException("Plan item instance for " + eventSubscription + " can not be found with empty sub scope id value");
        }
        
        CmmnRuntimeService cmmnRuntimeService = cmmnEngineConfiguration.getCmmnRuntimeService();
        PlanItemInstance planItemInstance = cmmnRuntimeService.createPlanItemInstanceQuery()
                        .planItemInstanceId(eventSubscription.getSubScopeId())
                        .singleResult();
        
        if (planItemInstance == null) {
            throw new FlowableException("Plan item instance for " + eventSubscription + " can not be found with sub scope id " + eventSubscription.getSubScopeId());
        }

        cmmnRuntimeService.createPlanItemInstanceTransitionBuilder(planItemInstance.getId())
            .variables(variables)
            .trigger();
    }

    @Override
    public void deleteCaseInstance(String caseInstanceId) {
        cmmnEngineConfiguration.getCommandExecutor().execute(commandContext -> {
            CaseInstanceEntity caseInstanceEntity = CommandContextUtil.getCaseInstanceEntityManager(commandContext).findById(caseInstanceId);
            if (caseInstanceEntity == null || caseInstanceEntity.isDeleted() || CaseInstanceState.isInTerminalState(caseInstanceEntity)) {
                return null;
            }

            CommandContextUtil.getAgenda(commandContext).planManualTerminateCaseInstanceOperation(caseInstanceEntity.getId());
            return null;
        });

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Check that the case instance / plan item still exists (createPlanItemInstanceQuery) before sending the signal, and skip if absent
  2. Review case model exit/sentry criteria so plan items are not terminated while signals are in flight
  3. Reduce async boundaries or ensure the signal and the terminating transition are not racing (serialize via same transaction/async executor config)
  4. Catch FlowableException around the signal call and treat 'already completed' as a benign outcome

Example fix

// before
cmmnRuntimeService.signalEventReceived(signalName, executionId);

// after
PlanItemInstance pii = cmmnRuntimeService.createPlanItemInstanceQuery()
    .planItemInstanceId(subScopeId).singleResult();
if (pii != null) {
    cmmnRuntimeService.createPlanItemInstanceTransitionBuilder(pii.getId()).trigger();
}
Defensive patterns

Strategy: try-catch

Validate before calling

PlanItemInstance pii = cmmnRuntimeService.createPlanItemInstanceQuery()
    .planItemInstanceId(subScopeId).singleResult();
if (pii == null) { /* already completed/terminated: skip signal */ }

Try / catch

try {
    cmmnRuntimeService.createPlanItemInstanceTransitionBuilder(planItemId).trigger();
} catch (FlowableException e) {
    if (e.getMessage().contains("can not be found with sub scope id")) {
        // plan item already gone; treat as benign
    } else { throw e; }
}

Prevention

When it happens

Trigger: A signal event handler resolves an EventSubscriptionEntity whose subScopeId no longer matches a live plan item instance (planItemInstanceQuery().planItemInstanceId(subScopeId).singleResult() returns null), typically because the plan item (stage/task) was completed, terminated, or the case instance ended before the signal was handled.

Common situations: Asynchronous signal delivery racing with case completion; signals fired after a plan item was exited by an exit criterion; stale event subscriptions left over from terminated stages; calling CmmnRuntimeService signal APIs for an already-finished case.

Understand the failure class

Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.

Related errors


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