{"record":{"id":"bca48f0c2b6a62d5","repo":"flowable/flowable-engine","slug":"no-process-instance-found-for-id","errorCode":null,"errorMessage":"No process instance found for id ''","messagePattern":"No process instance found for id ''","errorType":"exception","errorClass":"FlowableObjectNotFoundException","httpStatus":null,"severity":"error","filePath":"modules/flowable-engine/src/main/java/org/flowable/engine/impl/persistence/entity/ExecutionEntityManagerImpl.java","lineNumber":455,"sourceCode":"            getHistoryManager().recordDeleteHistoricProcessInstancesByProcessDefinitionId(processDefinitionId);\n        }\n    }\n    \n    @Override\n    public void deleteProcessInstance(String processInstanceId, String deleteReason, boolean cascade) {\n        deleteProcessInstance(processInstanceId, deleteReason, cascade, false);\n    }\n    \n    @Override\n    public void deleteProcessInstance(String processInstanceId, String deleteReason, boolean cascade, boolean directDeleteInDatabase) {\n        ExecutionEntity processInstanceExecution = findById(processInstanceId);\n\n        if (engineConfiguration.getEndProcessInstanceInterceptor() != null) {\n            engineConfiguration.getEndProcessInstanceInterceptor().beforeEndProcessInstance(processInstanceExecution, ProcessInstanceState.CANCELLED);\n        }\n\n        if (processInstanceExecution == null) {\n            throw new FlowableObjectNotFoundException(\"No process instance found for id '\" + processInstanceId + \"'\", ProcessInstance.class);\n        }\n\n        deleteProcessInstanceCascade(processInstanceExecution, ProcessInstanceState.CANCELLED, deleteReason, cascade, directDeleteInDatabase);\n        \n        // Special care needed for a process instance of a call activity: the parent process instance needs to be triggered for completion\n        // This can't be added to the deleteProcessInstanceCascade method, as this will also trigger all child and/or multi-instance\n        // process instances for child call activities, which shouldn't happen.\n        if (processInstanceExecution.getSuperExecutionId() != null) {\n            ExecutionEntity superExecution = processInstanceExecution.getSuperExecution();\n            if (superExecution != null\n                    && superExecution.getCurrentFlowElement() instanceof FlowNode flowNode\n                    && flowNode.getBehavior() instanceof SubProcessActivityBehavior subProcessActivityBehavior) {\n                try {\n                    subProcessActivityBehavior.completing(superExecution, processInstanceExecution);\n                    superExecution.setSubProcessInstance(null);\n                    subProcessActivityBehavior.completed(superExecution);\n                } catch (Exception e) {\n                    throw new FlowableException(\"Could not complete parent process instance for call activity with process instance execution \" ","sourceCodeStart":437,"sourceCodeEnd":473,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-engine/src/main/java/org/flowable/engine/impl/persistence/entity/ExecutionEntityManagerImpl.java#L437-L473","documentation":"ExecutionEntityManagerImpl.deleteProcessInstance looks up the process instance execution by id before cascading a delete. When findById returns null (no execution with that id exists, or the id points to a non-process-instance execution that cannot be loaded), it throws FlowableObjectNotFoundException with ProcessInstance.class. This is Flowable's not-found signal for runtimeService.deleteProcessInstance().","triggerScenarios":"Calling runtimeService.deleteProcessInstance(processInstanceId, reason) with an id that never existed, was mistyped, or whose instance already ended (suspended/completed/cancelled and removed from ACT_RU_EXECUTION); deleting concurrently from another thread/job so the instance is gone by the time this runs.","commonSituations":"Batch cleanup scripts hitting already-completed instances; user-supplied instance ids not validated; race between a timeout/cancel job and a user completing the instance; environments cleaned by history-level cleanup while ids are kept in a UI.","solutions":["Check existence first: runtimeService.createProcessInstanceQuery().processInstanceId(id).count() before deleting, and skip when 0.","Catch FlowableObjectNotFoundException around deleteProcessInstance and treat it as already-deleted/idempotent.","Verify the id is a process-instance execution id (root execution), not an inner execution/task id.","Fix concurrency: serialize cancel/complete operations or re-check state after a FlowableOptimisticLocking/NotFound failure."],"exampleFix":"// before\nruntimeService.deleteProcessInstance(instanceId, \"cleanup\");\n\n// after\nif (runtimeService.createProcessInstanceQuery()\n        .processInstanceId(instanceId).count() > 0) {\n    runtimeService.deleteProcessInstance(instanceId, \"cleanup\");\n}","handlingStrategy":"validation","validationCode":"if (runtimeService.createProcessInstanceQuery()\n        .processInstanceId(instanceId).count() == 0) {\n    return; // nothing to delete\n}","typeGuard":null,"tryCatchPattern":"try {\n    runtimeService.deleteProcessInstance(instanceId, reason);\n} catch (FlowableObjectNotFoundException e) {\n    // already gone: treat as idempotent success\n}","preventionTips":["Validate instance ids before deleting (query first, delete second).","Design cleanup jobs to tolerate already-completed instances.","Don't pass task/execution ids where a process instance id is expected."],"tags":["flowable","process-instance","not-found","delete"],"backgroundTag":"record-not-found","analyzedSha":"d6d39ce1c69ff244f2d9dc6af756a9b95e865586","analyzedAt":"2026-09-11T06:41:19.413Z","contentChangedAt":"2026-09-11T06:41:19.413Z","schemaVersion":2},"datasetVersion":"2026-09-18T11:17:12.947Z"}