flowable/flowable-engine · error · FlowableObjectNotFoundException

execution ${executionId} doesn't exist

Error message

execution ${executionId} doesn't exist

What it means

Flowable throws FlowableObjectNotFoundException when the executionId given to GetExecutionVariablesCmd does not match any execution in the database. The id is non-null but resolves to nothing, so the command aborts. Message: 'execution <id> doesn't exist'.

Source

Thrown at modules/flowable-engine/src/main/java/org/flowable/engine/impl/cmd/GetExecutionVariablesCmd.java:57

    public GetExecutionVariablesCmd(String executionId, Collection<String> variableNames, boolean isLocal) {
        this.executionId = executionId;
        this.variableNames = variableNames;
        this.isLocal = isLocal;
    }

    @Override
    public Map<String, Object> execute(CommandContext commandContext) {

        // Verify existence of execution
        if (executionId == null) {
            throw new FlowableIllegalArgumentException("executionId is null");
        }

        ExecutionEntity execution = CommandContextUtil.getExecutionEntityManager(commandContext).findById(executionId);

        if (execution == null) {
            throw new FlowableObjectNotFoundException("execution " + executionId + " doesn't exist", Execution.class);
        }

        if (Flowable5Util.isFlowable5ProcessDefinitionId(commandContext, execution.getProcessDefinitionId())) {
            Flowable5CompatibilityHandler compatibilityHandler = Flowable5Util.getFlowable5CompatibilityHandler();
            return compatibilityHandler.getExecutionVariables(executionId, variableNames, isLocal);
        }

        if (variableNames == null || variableNames.isEmpty()) {

            // Fetch all

            if (isLocal) {
                return execution.getVariablesLocal();
            } else {
                return execution.getVariables();
            }

        } else {

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Re-resolve a current execution id before reading variables
  2. Catch FlowableObjectNotFoundException and return a sensible default/empty result
  3. Use the history service (HistoricVariableInstanceQuery) for variables of finished instances
  4. Verify engine/database targeting

Example fix

// before
Map<String, Object> vars = runtimeService.getVariables(executionId);
// after
try {
    Map<String, Object> vars = runtimeService.getVariables(executionId);
} catch (FlowableObjectNotFoundException e) {
    Map<String, Object> vars = historyService.createHistoricVariableInstanceQuery()
        .executionId(executionId).list().stream()
        .collect(Collectors.toMap(HistoricVariableInstance::getVariableName, HistoricVariableInstance::getValue));
}
Defensive patterns

Strategy: try-catch

Validate before calling

Execution e = runtimeService.createExecutionQuery().executionId(executionId).singleResult();
if (e == null) throw new IllegalStateException("Execution not found: " + executionId);

Try / catch

try { ... } catch (FlowableObjectNotFoundException e) { /* fall back to HistoricVariableInstanceQuery */ }

Prevention

When it happens

Trigger: RuntimeService.getVariables(staleExecutionId) after the execution completed; ids from another engine/cluster; manually fabricated ids.

Common situations: Async jobs outliving the process; user-facing UIs holding ids across page reloads while the instance finished; environment drift (test id against prod engine).

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/16fc3e8831fd9b65. Report an issue: GitHub.