flowable/flowable-engine · error · FlowableObjectNotFoundException

Could not find an plan item instance with id

Error message

Could not find an plan item instance with id '${id}'.

What it means

getPlanItemInstanceFromRequest queries the CMMN runtime for a plan item instance by id (including ended instances) and throws FlowableObjectNotFoundException when no match exists. The id is therefore not a live (or previously active) plan item instance in this engine, or the instance was removed/completed and purged.

Solutions

  1. Verify the planItemInstanceId exists via the CMMN engine or case query before calling.
  2. Re-query the case instance to obtain fresh plan item instance ids when a case has progressed.
  3. Check tenant/database configuration so you query the engine that actually owns the id.
  4. Catch FlowableObjectNotFoundException (HTTP 404) and treat the resource as gone, prompting a refresh of ids.

Example fix

// before
client.post("/cmmn-runtime/plan-item-instances/" + staleId + "/action", body);
// after
PlanItemInstance p = freshCaseQuery().planItemInstanceId(id).singleResult();
if (p != null) client.post("/cmmn-runtime/plan-item-instances/" + id + "/action", body);
Defensive patterns

Strategy: try-catch

Validate before calling

const exists = await fetch(`/cmmn-query/plan-item-instances/${id}`).then(r => r.ok);

Try / catch

try { await getPlanItemInstance(id); } catch (e) { if (e.status === 404) { refreshCasePlanItemIds(); return null; } throw e; }

Prevention

When it happens

Trigger: GET .../cmmn-runtime/plan-item-instances/{planItemInstanceId}, or POST actions (complete/enable/disable/start) on a plan item instance id that does not exist in the runtime database.

Common situations: Stale ids cached on the client after the case instance finished; wrong tenant/datasource; referencing a task/execution id instead of a plan item instance id; database cleaned or restarted between calls.

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

Appendix: source

Thrown at modules/flowable-cmmn-rest/src/main/java/org/flowable/cmmn/rest/service/api/runtime/planitem/PlanItemInstanceBaseResource.java:224

                    if (isCase) {
                        planItemInstanceQuery.caseVariableValueNotEqualsIgnoreCase(variable.getName(), (String) actualValue);
                    } else {
                        planItemInstanceQuery.variableValueNotEqualsIgnoreCase(variable.getName(), (String) actualValue);
                    }
                } else {
                    throw new FlowableIllegalArgumentException("Only string variable values are supported when ignoring casing, but was: " + actualValue.getClass().getName());
                }
                break;
            default:
                throw new FlowableIllegalArgumentException("Unsupported variable query operation: " + variable.getVariableOperation());
            }
        }
    }

    protected PlanItemInstance getPlanItemInstanceFromRequest(String planItemInstanceId) {
        PlanItemInstance planItemInstance = runtimeService.createPlanItemInstanceQuery().planItemInstanceId(planItemInstanceId).includeEnded().singleResult();
        if (planItemInstance == null) {
            throw new FlowableObjectNotFoundException("Could not find an plan item instance with id '" + planItemInstanceId + "'.", PlanItemInstance.class);
        }
        
        if (restApiInterceptor != null) {
            restApiInterceptor.accessPlanItemInstanceInfoById(planItemInstance);
        }
        
        return planItemInstance;
    }

    protected Map<String, Object> getVariablesToSet(List<RestVariable> restVariables) {
        Map<String, Object> variablesToSet = new HashMap<>();
        for (RestVariable var : restVariables) {
            if (var.getName() == null) {
                throw new FlowableIllegalArgumentException("Variable name is required");
            }

            Object actualVariableValue = restResponseFactory.getVariableValue(var);

View on GitHub (pinned to d6d39ce1c6)