{"record":{"id":"26fa5d3883e8d08d","repo":"flowable/flowable-engine","slug":"lazy-loading-outside-command-context-for-26fa5d","errorCode":null,"errorMessage":"lazy loading outside command context for ","messagePattern":"lazy loading outside command context for ","errorType":"exception","errorClass":"FlowableException","httpStatus":null,"severity":"error","filePath":"modules/flowable-task-service/src/main/java/org/flowable/task/service/impl/persistence/entity/TaskEntityImpl.java","lineNumber":448,"sourceCode":"\n    @Override\n    public void setFormKey(String formKey) {\n        this.formKey = formKey;\n    }\n\n    // Override from VariableScopeImpl\n\n    @Override\n    protected boolean isPropagateToHistoricVariable() {\n        return true;\n    }\n\n    // Overridden to avoid fetching *all* variables (as is the case in the super // call)\n    @Override\n    protected VariableInstanceEntity getSpecificVariable(String variableName) {\n        CommandContext commandContext = Context.getCommandContext();\n        if (commandContext == null) {\n            throw new FlowableException(\"lazy loading outside command context for \" + this);\n        }\n\n        return getVariableServiceConfiguration().getVariableService()\n                .createInternalVariableInstanceQuery()\n                .taskId(id)\n                .name(variableName)\n                .singleResult();\n    }\n\n    @Override\n    protected List<VariableInstanceEntity> getSpecificVariables(Collection<String> variableNames) {\n        CommandContext commandContext = Context.getCommandContext();\n        if (commandContext == null) {\n            throw new FlowableException(\"lazy loading outside command context for \" + this);\n        }\n        return getVariableServiceConfiguration().getVariableService()\n                .createInternalVariableInstanceQuery()\n                .taskId(id)","sourceCodeStart":430,"sourceCodeEnd":466,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-task-service/src/main/java/org/flowable/task/service/impl/persistence/entity/TaskEntityImpl.java#L430-L466","documentation":"TaskEntityImpl.getSpecificVariable() lazily fetches a single variable instance, which requires an active Flowable CommandContext. Flowable throws FlowableException when the entity is accessed outside a command (e.g. in a non-managed thread or after the command context closed).","triggerScenarios":"Calling taskEntity.getVariable(name) (or similar accessors hitting getSpecificVariable) from application code without wrapping in managementService.executeCommand(...), or retaining/using the entity after the command context ended (e.g. in an async executor thread).","commonSituations":"Detached task entities used in servlet/REST threads outside the Flowable command interceptor chain; storing entities across async boundaries; custom code bypassing the taskService and accessing entities directly.","solutions":["Access variables via TaskService.getVariable(taskId, name) instead of the entity so Flowable opens a command context","Wrap direct entity access in managementService.executeCommand(...)","Re-fetch the entity inside the current command rather than caching it across commands"],"exampleFix":"// before\nTaskEntity entity = (TaskEntity) task; // detached\nentity.getVariable(\"score\"); // lazy load -> throws\n// after\nObject score = taskService.getVariable(task.getId(), \"score\");","handlingStrategy":"try-catch","validationCode":"if (Context.getCommandContext() == null) {\n    // not inside a command: use the service API instead\n    Object value = taskService.getVariable(taskId, variableName);\n}","typeGuard":"boolean canLazyLoad() { return Context.getCommandContext() != null; }","tryCatchPattern":"try {\n    Object value = taskEntity.getVariable(variableName);\n} catch (FlowableException e) {\n    if (e.getMessage().startsWith(\"lazy loading outside command context\")) {\n        Object value = taskService.getVariable(taskEntity.getId(), variableName); // re-fetch via service\n    } else throw e;\n}","preventionTips":["Prefer TaskService APIs over direct entity access","Never cache task entities across command boundaries or into async threads","Wrap direct entity access in managementService.executeCommand"],"tags":["flowable","lazy-loading","command-context","entity"],"backgroundTag":"invalid-state-transition","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"}