flowable/flowable-engine · error · FlowableObjectNotFoundException

Could not find a variable with name

Error message

Could not find a variable with name '${variableName}'.

What it means

Thrown by deleteVariable when runtimeService.hasVariable reports that the case instance has no variable with the requested name. This is a FlowableObjectNotFoundException (HTTP 404) raised before the deletion, so the variable set is unchanged. Check the case instance id and scope if you believe the variable exists.

Solutions

  1. Verify the variable exists first via GET /cmmn-runtime/case-instances/{id}/variables and use the exact returned name.
  2. Confirm the caseInstanceId is correct and the case instance is still running.
  3. Check whether the variable is a task-local variable and use the task variable endpoint instead.
  4. Make delete calls idempotent in your client: ignore 404 FlowableObjectNotFoundException when the desired end state is 'variable absent'.

Example fix

// before
deleteVariable(caseInstanceId, "appoved") // 404

// after
// GET .../variables -> ["approved", ...]
deleteVariable(caseInstanceId, "approved")
Defensive patterns

Strategy: try-catch

Validate before calling

// Optional pre-check
const vars = await getCaseVariables(caseInstanceId);
if (!vars.some(v => v.name === variableName)) {
  return; // nothing to delete
}

Try / catch

try {
  await deleteCaseVariable(caseInstanceId, variableName);
} catch (e) {
  if (e.status === 404) {
    // variable already absent — treat as success
    return;
  }
  throw e;
}

Prevention

When it happens

Trigger: DELETE /cmmn-runtime/case-instances/{caseInstanceId}/variables/{variableName} where hasVariable(caseInstanceId, variableName) returns false — variable never set, already deleted, name misspelled, or caseInstanceId wrong.

Common situations: Deleting a variable twice (second call 404s); case-sensitivity mismatch in variable names; variable belongs to a task/process scope rather than the case scope; stale client cache after the case instance moved on or completed.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


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

Appendix: source

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

            setSimpleVariable(restVariable, caseInstance.getId(), false, true, RestVariable.RestVariableScope.GLOBAL, CmmnRestResponseFactory.VARIABLE_CASE, createVariableInterceptor(caseInstance));
        }
    }

    @ApiOperation(value = "Delete a variable", tags = { "Case Instance Variables" }, nickname = "deleteCaseInstanceVariable", code = 204)
    @ApiResponses(value = {
            @ApiResponse(code = 204, message = "Indicates the variable was found and has been deleted. Response-body is intentionally empty."),
            @ApiResponse(code = 404, message = "Indicates the requested variable was not found.")
    })
    @DeleteMapping(value = "/cmmn-runtime/case-instances/{caseInstanceId}/variables/{variableName}")
    @ResponseStatus(HttpStatus.NO_CONTENT)
    public void deleteVariable(@ApiParam(name = "caseInstanceId") @PathVariable("caseInstanceId") String caseInstanceId, @ApiParam(name = "variableName") @PathVariable("variableName") String variableName,
            @RequestParam(value = "scope", required = false) String scope) {

        CaseInstance caseInstance = getCaseInstanceFromRequestWithoutAccessCheck(caseInstanceId);
        
        boolean hasVariable = runtimeService.hasVariable(caseInstance.getId(), variableName);
        if (!hasVariable) {
            throw new FlowableObjectNotFoundException("Could not find a variable with name '" + variableName + "'.");
        }
        
        if (restApiInterceptor != null) {
            restApiInterceptor.deleteCaseInstanceVariables(caseInstance, Collections.singleton(variableName));
        }

        runtimeService.removeVariable(caseInstance.getId(), variableName);
    }
}

View on GitHub (pinned to d6d39ce1c6)