{"record":{"id":"4f5f65f6b2073522","repo":"flowable/flowable-engine","slug":"invalid-usage-of-type-job-handler-variable-sco","errorCode":null,"errorMessage":"Invalid usage of ${TYPE} job handler, variable scope is of type ${variableScope.getClass()}","messagePattern":"Invalid usage of (.+?) job handler, variable scope is of type (.+?)","errorType":"exception","errorClass":"FlowableException","httpStatus":null,"severity":"error","filePath":"modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/job/AsyncLeaveActivePlanItemInstanceJobHandler.java","lineNumber":91,"sourceCode":"                    if (errorCode != null) {\n                        String errorMessage = jsonConfiguration.path(OperationSerializationMetadata.FIELD_ERROR_MESSAGE).stringValue(null);\n                        CmmnFault reconstructedError = errorMessage != null ? new CmmnFault(errorCode, errorMessage) : new CmmnFault(errorCode);\n                        CommandContextUtil.getAgenda(commandContext).planFailPlanItemInstanceOperation(planItemInstanceEntity, reconstructedError);\n                    } else {\n                        CommandContextUtil.getAgenda(commandContext).planFailPlanItemInstanceOperation(planItemInstanceEntity);\n                    }\n\n                } else {\n                    throw new FlowableException(\"Programmatic error: unsupported transition \" + transition + \" for \" + planItemInstanceEntity);\n\n                }\n\n            } catch (Exception e) {\n                throw new FlowableException(\"Could not deserialize job configuration\", e);\n            }\n\n        } else {\n            throw new FlowableException(\"Invalid usage of \" + TYPE + \" job handler, variable scope is of type \" + variableScope.getClass());\n        }\n    }\n\n}\n","sourceCodeStart":73,"sourceCodeEnd":96,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/job/AsyncLeaveActivePlanItemInstanceJobHandler.java#L73-L96","documentation":"AsyncLeaveActivePlanItemInstanceJobHandler requires the variable scope passed by the job executor to be a CaseInstanceEntity; any other VariableScope type means the job was invoked in an invalid way. The handler throws FlowableException naming the actual scope class so miswiring is visible immediately.","triggerScenarios":"execute(job, caseInstanceId, variableScope, commandContext) receives a variableScope whose class is not CaseInstanceEntity — e.g. the job was created/attached to the wrong scope or a custom job/handler dispatches it with a process or task variable scope.","commonSituations":"Custom job creation code binding the async leave job to the wrong entity; engine customization or subclassed job dispatch passing the wrong scope; mixing BPMN (ProcessInstance) and CMMN (CaseInstance) job handling in a shared executor setup.","solutions":["Verify the async job is created for a CMMN case instance (CaseInstanceEntity scope), not a BPMN process scope.","If you create these jobs via custom code, resolve and pass the CaseInstanceEntity when scheduling the job.","Check any subclass/override of the job handler dispatch logic that may supply the wrong variable scope.","Confirm you are not mixing flowable-engine and flowable-cmmn-engine job handlers on shared job definitions."],"exampleFix":"// before: handler invoked with a generic scope\njobHandler.execute(job, caseInstanceId, taskEntity, commandContext);\n// after\nCaseInstanceEntity caseInstance = CommandContextUtil.getCaseInstanceEntityManager(commandContext).findById(caseInstanceId);\njobHandler.execute(job, caseInstanceId, caseInstance, commandContext);","handlingStrategy":"type-guard","validationCode":"if (!(scope instanceof CaseInstanceEntity)) {\n    throw new IllegalArgumentException(\"AsyncLeaveActivePlanItemInstanceJobHandler requires CaseInstanceEntity scope\");\n}","typeGuard":"boolean validScope(VariableScope scope) {\n    return scope instanceof CaseInstanceEntity;\n}","tryCatchPattern":"try {\n    // custom dispatch of job handler\n} catch (FlowableException e) {\n    if (e.getMessage() != null && e.getMessage().contains(\"variable scope is of type\")) {\n        throw new IllegalStateException(\"Job attached to wrong scope; re-create job against the case instance\", e);\n    }\n    throw e;\n}","preventionTips":["Create CMMN async jobs only against case instance scopes","Do not subclass/redirect job handler dispatch between BPMN and CMMN engines","Add integration tests running async jobs end-to-end after engine customizations"],"tags":["flowable","cmmn","async-job","type-mismatch","job-handler"],"backgroundTag":"config-type-mismatch","analyzedSha":"d6d39ce1c69ff244f2d9dc6af756a9b95e865586","analyzedAt":"2026-09-11T06:41:19.413Z","contentChangedAt":"2026-09-11T06:41:19.413Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}