flowable/flowable-engine · error · FlowableException
RuntimeService cannot be null, Obtain your builder instance
Error message
RuntimeService cannot be null, Obtain your builder instance from the RuntimeService to access this feature
What it means
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().
Source
Thrown at modules/flowable-engine/src/main/java/org/flowable/engine/impl/runtime/ChangeActivityStateBuilderImpl.java:234
return this;
}
@Override
public ChangeActivityStateBuilder localVariables(String startActivityId, Map<String, Object> localVariables) {
if (this.localVariables == null) {
this.localVariables = new HashMap<>();
}
this.localVariables.put(startActivityId, localVariables);
return this;
}
@Override
public void changeState() {
if (runtimeService == null) {
throw new FlowableException("RuntimeService cannot be null, Obtain your builder instance from the RuntimeService to access this feature");
}
runtimeService.changeActivityState(this);
}
public String getProcessInstanceId() {
return processInstanceId;
}
public List<MoveExecutionIdContainer> getMoveExecutionIdList() {
return moveExecutionIdList;
}
public List<MoveActivityIdContainer> getMoveActivityIdList() {
return moveActivityIdList;
}
public List<EnableActivityIdContainer> getEnableActivityIdList() {
return enableActivityIdList;View on GitHub (pinned to d6d39ce1c6)
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.
Example fix
// before
new ChangeActivityStateBuilderImpl()
.processInstanceId(pid)
.moveActivityIdTo("task1", "task2")
.changeState(); // throws
// after
runtimeService.createChangeActivityStateBuilder()
.processInstanceId(pid)
.moveActivityIdTo("task1", "task2")
.changeState(); Defensive patterns
Strategy: validation
Validate before calling
if (runtimeService == null) throw new IllegalStateException("Obtain ChangeActivityStateBuilder from runtimeService.createChangeActivityStateBuilder()"); Try / catch
try {
runtimeService.createChangeActivityStateBuilder()...changeState();
} catch (FlowableException e) {
log.error("changeActivityState failed: {}", e.getMessage());
throw e;
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: "not installed", "pip install", "required for": how missing-dependency errors surface across open-source libraries — this error's family across 34 libraries.
Related errors
- No processDefinitionId, processDefinitionKey nor messageName
- No processDefinitionId, processDefinitionKey provided
- The process instance id is mandatory, but '${processInstance
- formInfo is null
- No process instance found for id = '" + processInstanceId +
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/28da2ee88d2be560.
Report an issue: GitHub.