{"record":{"id":"41e832918dd56402","repo":"flowable/flowable-engine","slug":"invalid-usage-of-type-job-handler-case-instanc","errorCode":null,"errorMessage":"Invalid usage of ${TYPE} job handler, case instance ${caseInstanceId} was not found.","messagePattern":"Invalid usage of (.+?) job handler, case instance (.+?) was not found\\.","errorType":"exception","errorClass":"FlowableException","httpStatus":null,"severity":"error","filePath":"modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/job/AsyncInitializePlanModelJobHandler.java","lineNumber":41,"sourceCode":"/**\n * @author martin.grofcik\n */\npublic class AsyncInitializePlanModelJobHandler implements JobHandler {\n    \n    public static final String TYPE = \"cmmn-async-init-plan-model-instance\";\n\n    @Override\n    public String getType() {\n        return TYPE;\n    }\n\n    @Override\n    public void execute(JobEntity job, String caseInstanceId, VariableScope variableScope, CommandContext commandContext) {\n        CaseInstanceEntity caseInstance = CommandContextUtil.getCaseInstanceEntityManager(commandContext).findById(caseInstanceId);\n        if (caseInstance != null) {\n            CommandContextUtil.getAgenda(commandContext).planInitPlanModelOperation(caseInstance);\n        } else {\n            throw new FlowableException(\"Invalid usage of \" + TYPE + \" job handler, case instance \" + caseInstanceId + \" was not found.\");\n        }\n    }\n\n}\n","sourceCodeStart":23,"sourceCodeEnd":46,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/job/AsyncInitializePlanModelJobHandler.java#L23-L46","documentation":"Flowable's async initialize-plan-model job handler runs when a delayed async case start job fires. It looks up the case instance by id and, if it no longer exists, cannot proceed to plan the init plan model operation, so it throws FlowableException. This indicates the async job is orphaned — its target case instance was deleted (e.g. via history cleanup, manual delete, or a rolled-back transaction) before the job executed.","triggerScenarios":"An async job of TYPE 'async-init-plan-model' is executed by the async executor but CommandContextUtil.getCaseInstanceEntityManager(...).findById(caseInstanceId) returns null, typically because the case instance row was removed between job creation and job execution.","commonSituations":"History/job cleanup jobs deleting case instance rows while async jobs remain; manual deletion of case instance data via SQL or API; running the async executor against a shared job table where another node already started and rolled back the case; restoring a database backup with jobs but without instance rows.","solutions":["Check whether the case instance actually still exists (ACT_CMMN_HI_CASEINST / case instance tables) for the id in the message; if it was intentionally deleted, delete the corresponding async job row so the executor stops retrying.","Investigate what removed the case instance (history cleanup config, manual deletes) and align job retention with case instance retention.","If this follows a failed case initialization transaction, verify the CMMN engine creates the case instance before scheduling the async init job and that no rollback leaves the job behind.","Reproduce the case start locally; if the case instance is missing because creation failed, fix the underlying creation error rather than the symptom."],"exampleFix":"// before: orphaned job retried forever, throwing\n// after: purge orphaned async jobs for missing case instances before execution\nCaseInstanceEntity caseInstance = commandContext.getCaseInstanceEntityManager().findById(caseInstanceId);\nif (caseInstance == null) {\n    commandContext.getJobManager().deleteJob(job);\n    return; // or log a warning instead of throwing\n}","handlingStrategy":"validation","validationCode":"CaseInstance ci = cmmnRuntimeService.createCaseInstanceQuery().caseInstanceId(id).singleResult();\nif (ci == null) throw new IllegalStateException(\"Case instance \" + id + \" gone before async init job ran\");","typeGuard":"boolean caseInstanceExists(String id) {\n    return cmmnRuntimeService.createCaseInstanceQuery().caseInstanceId(id).count() > 0;\n}","tryCatchPattern":"try {\n    // start case / wait for async init\n} catch (FlowableException e) {\n    if (e.getMessage() != null && e.getMessage().contains(\"was not found\")) {\n        log.warn(\"Orphaned async init job for missing case instance; purging job\");\n        jobService.deleteJob(jobId);\n    } else { throw e; }\n}","preventionTips":["Align history/job cleanup retention so async jobs never outlive their case instances","Monitor dead-letter jobs and alert on 'was not found' messages","Avoid deleting case instance rows directly via SQL","Test case-start failure paths in CI so jobs are not left orphaned"],"tags":["flowable","cmmn","async-job","orphaned-job","case-instance"],"backgroundTag":"entity-not-found","analyzedSha":"d6d39ce1c69ff244f2d9dc6af756a9b95e865586","analyzedAt":"2026-09-11T06:41:19.413Z","contentChangedAt":"2026-09-11T06:41:19.413Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}