flowable/flowable-engine · error · FlowableObjectNotFoundException

Plan item instance '${instanceId}' doesn't have a variable w

Error message

Plan item instance '${instanceId}' doesn't have a variable with name: '${variableName}'.

What it means

When the requested variable name is not present on the plan item instance, runtimeService.getLocalVariable returns null and the method throws FlowableObjectNotFoundException scoped to VariableInstance. This is a per-instance variable lookup failure, not a global variable absence.

Source

Thrown at modules/flowable-cmmn-rest/src/main/java/org/flowable/cmmn/rest/service/api/runtime/caze/BaseVariableResource.java:120

            restApiInterceptor.accessPlanItemInstanceVariable(planItemInstance, variableName);
        }
        return getVariableFromRequestWithoutAccessCheck(planItemInstance.getId(), variableName, CmmnRestResponseFactory.VARIABLE_PLAN_ITEM, includeBinary);
    }

    protected RestVariable getVariableFromRequestWithoutAccessCheck(String instanceId, String variableName, int variableType, boolean includeBinary) {
        Object value = null;

        if (variableType == CmmnRestResponseFactory.VARIABLE_PLAN_ITEM) {
            value = runtimeService.getLocalVariable(instanceId, variableName);
        } else if (variableType == CmmnRestResponseFactory.VARIABLE_CASE) {
            value = runtimeService.getVariable(instanceId, variableName);
        } else {
            throw new FlowableIllegalArgumentException("Unknown variable type " + variableType);
        }

        if (value == null) {
            if (variableType == CmmnRestResponseFactory.VARIABLE_PLAN_ITEM) {
                throw new FlowableObjectNotFoundException(
                        "Plan item instance '" + instanceId + "' doesn't have a variable with name: '" + variableName + "'.",
                        VariableInstance.class);
            } else {
                throw new FlowableObjectNotFoundException(
                        "Case instance '" + instanceId + "' doesn't have a variable with name: '" + variableName + "'.",
                        VariableInstance.class);
            }
        }

        //we use null for the scope, because the extraction from request does not require the scope
        return constructRestVariable(variableName, value, instanceId, variableType, includeBinary, null);
    }

    protected byte[] getVariableDataByteArray(CaseInstance caseInstance, String variableName, HttpServletResponse response) {
        RestVariable variable = getVariableFromRequest(caseInstance, variableName, true);
        return restVariableDataToRestResponse(variable, response);
    }

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. List existing plan item variables first (GET plan-item variables collection) to confirm the name
  2. Read case-scoped variables via the case-instance variable endpoint if the variable lives at case scope
  3. Check name spelling/case exactly
  4. Use history variable endpoints if the plan item already completed

Example fix

// before
GET /cmmn-runtime/plan-item-instances/{id}/variables/caseVar // local lookup misses case-scoped var
// after
GET /cmmn-runtime/case-instances/{caseId}/variables/caseVar
Defensive patterns

Strategy: try-catch

Validate before calling

const vars = await fetch(`/cmmn-runtime/plan-item-instances/${id}/variables`);
const names = (await vars.json()).map(v => v.name);
if (!names.includes(variableName)) throw new Error('Variable not present locally: ' + variableName);

Try / catch

try { ... } catch (e) {
  if (e instanceof FlowableObjectNotFoundException) { /* check case-scope or history */ }
}

Prevention

When it happens

Trigger: GET/PUT/DELETE of a variable on a plan-item variable endpoint where the variableName does not exist locally on that plan item instance.

Common situations: Variable set on the case (process-level) scope but read with the plan-item local endpoint; variable created after the request; case-sensitive name mismatch; variable removed by another actor.

Understand the failure class

Background: Record Not Found Errors: "not found", RecordNotFound, and "was not found" — what they mean and how to fix them — this error's family across 28 libraries.

Related errors


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