{"record":{"id":"28da2ee88d2be560","repo":"flowable/flowable-engine","slug":"runtimeservice-cannot-be-null-obtain-your-builder","errorCode":null,"errorMessage":"RuntimeService cannot be null, Obtain your builder instance from the RuntimeService to access this feature","messagePattern":"RuntimeService cannot be null, Obtain your builder instance from the RuntimeService to access this feature","errorType":"exception","errorClass":"FlowableException","httpStatus":null,"severity":"error","filePath":"modules/flowable-engine/src/main/java/org/flowable/engine/impl/runtime/ChangeActivityStateBuilderImpl.java","lineNumber":234,"sourceCode":"\n        return this;\n    }\n\n    @Override\n    public ChangeActivityStateBuilder localVariables(String startActivityId, Map<String, Object> localVariables) {\n        if (this.localVariables == null) {\n            this.localVariables = new HashMap<>();\n        }\n\n        this.localVariables.put(startActivityId, localVariables);\n\n        return this;\n    }\n\n    @Override\n    public void changeState() {\n        if (runtimeService == null) {\n            throw new FlowableException(\"RuntimeService cannot be null, Obtain your builder instance from the RuntimeService to access this feature\");\n        }\n        runtimeService.changeActivityState(this);\n    }\n\n    public String getProcessInstanceId() {\n        return processInstanceId;\n    }\n\n    public List<MoveExecutionIdContainer> getMoveExecutionIdList() {\n        return moveExecutionIdList;\n    }\n\n    public List<MoveActivityIdContainer> getMoveActivityIdList() {\n        return moveActivityIdList;\n    }\n\n    public List<EnableActivityIdContainer> getEnableActivityIdList() {\n        return enableActivityIdList;","sourceCodeStart":216,"sourceCodeEnd":252,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-engine/src/main/java/org/flowable/engine/impl/runtime/ChangeActivityStateBuilderImpl.java#L216-L252","documentation":"ChangeActivityStateBuilderImpl.changeState delegates to RuntimeService.changeActivityState. The builder can be constructed without a RuntimeService (e.g. via its no-arg constructor), and in that case moving activity state is impossible, so a FlowableException is thrown telling you to obtain the builder from RuntimeService.createChangeActivityStateBuilder().","triggerScenarios":"Instantiating new ChangeActivityStateBuilderImpl() directly (or via a builder obtained from a service that did not wire runtimeService) and calling changeState; frameworks deserializing/migrating builders where runtimeService was not injected.","commonSituations":"Custom migration tooling constructing the impl class directly; tests instantiating the builder manually; code copied from internal engine usage where CommandContext-based construction is valid but standalone callers lack the service.","solutions":["Create the builder through the API: runtimeService.createChangeActivityStateBuilder()...changeState().","Ensure the RuntimeService reference is injected/non-null wherever the builder is created.","If writing engine-internal code, use the manager/command-context path instead of the standalone builder.","Do not construct impl classes from *Impl packages in application code."],"exampleFix":"// before\nnew ChangeActivityStateBuilderImpl()\n    .processInstanceId(pid)\n    .moveActivityIdTo(\"task1\", \"task2\")\n    .changeState(); // throws\n// after\nruntimeService.createChangeActivityStateBuilder()\n    .processInstanceId(pid)\n    .moveActivityIdTo(\"task1\", \"task2\")\n    .changeState();","handlingStrategy":"validation","validationCode":"if (runtimeService == null) throw new IllegalStateException(\"Obtain ChangeActivityStateBuilder from runtimeService.createChangeActivityStateBuilder()\");","typeGuard":null,"tryCatchPattern":"try {\n    runtimeService.createChangeActivityStateBuilder()...changeState();\n} catch (FlowableException e) {\n    log.error(\"changeActivityState failed: {}\", e.getMessage());\n    throw e;\n}","preventionTips":["Never instantiate *Impl classes directly; always use service factory methods.","Inject RuntimeService where state migration code runs.","In tests, build the engine (or mock RuntimeService) before creating builders.","Review imports: ChangeActivityStateBuilderImpl is internal API."],"tags":["java","flowable","process-instance","change-state","misuse-of-api"],"backgroundTag":"missing-dependency","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"}