flowable/flowable-engine · error · FlowableException
Cannot get process model: no current command context is…
Error message
Cannot get process model: no current command context is active
What it means
The process model for a process definition is resolved through the command context. ProcessDefinitionUtil.getProcess requires an active CommandContext (set up by engine services/commands); when Context.getCommandContext() is null it cannot access engine internals and throws this FlowableException. It typically means the method is being called outside an engine command/transaction.
Solutions
- Run the logic inside a command: processEngineConfiguration.getCommandExecutor().execute(new Command<Process>() { ... }) or managementService.executeCommand(...).
- Call public engine services (RepositoryService / RuntimeService) instead of internal ProcessDefinitionUtil to let the engine establish the command context.
- If in a custom async thread, propagate the CommandContext explicitly using Context/CommandContextUtil within a command wrapper.
- In tests, use the engine's command executor helper rather than static util access.
Example fix
// before
Process process = ProcessDefinitionUtil.getProcess(processDefinitionId); // no context
// after
Process process = processEngine.getManagementService().executeCommand(
commandContext -> ProcessDefinitionUtil.getProcess(processDefinitionId)); Defensive patterns
Strategy: try-catch
Validate before calling
// verify a command context is active before calling internals
if (Context.getCommandContext() == null) {
// route through the engine instead of calling the util directly
} Try / catch
try {
Process p = managementService.executeCommand(
ctx -> ProcessDefinitionUtil.getProcess(processDefinitionId));
} catch (FlowableException e) {
if (e.getMessage().contains("no current command context")) {
throw new IllegalStateException("Wrap internal calls in a command", e);
}
throw e;
} Prevention
- Never call engine internal util classes from raw threads; use command executor
- Prefer public RepositoryService/RuntimeService APIs over internals
- In custom async work, always establish a CommandContext via CommandExecutor
When it happens
Trigger: Calling getProcess(processDefinitionId) from non-command code such as a plain thread, a servlet filter, an application startup hook, or test code that has not wrapped the call in a command (e.g. managementService.executeCommand or an engine service call).
Common situations: Custom extensions calling internal util classes directly instead of going through engine services; asynchronous jobs or scheduled threads without command context propagation; unit tests invoking engine internals without CommandContextUtil initialization.
Related errors
- lazy loading outside command context for
- Call was interrupted
- Cannot initialize byte array. There is no command context…
- Cannot use startProcessByName in an active command.
- Cannot use this method of the BusinessProcess bean within…
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/1c8e09566724a8fd.
Report an issue: GitHub.
Appendix: source
Thrown at modules/flowable-engine/src/main/java/org/flowable/engine/impl/util/ProcessDefinitionUtil.java:83
}
public static ProcessDefinition getProcessDefinition(String processDefinitionId, boolean checkCacheOnly, ProcessEngineConfigurationImpl processEngineConfiguration) {
if (checkCacheOnly) {
ProcessDefinitionCacheEntry cacheEntry = processEngineConfiguration.getProcessDefinitionCache().get(processDefinitionId);
if (cacheEntry != null) {
return cacheEntry.getProcessDefinition();
}
return null;
} else {
// This will check the cache in the findDeployedProcessDefinitionById method
return processEngineConfiguration.getDeploymentManager().findDeployedProcessDefinitionById(processDefinitionId);
}
}
public static Process getProcess(String processDefinitionId) {
if (Context.getCommandContext() == null) {
throw new FlowableException("Cannot get process model: no current command context is active");
} else if (CommandContextUtil.getProcessEngineConfiguration() == null) {
return Flowable5Util.getFlowable5CompatibilityHandler().getProcessDefinitionProcessObject(processDefinitionId);
} else {
DeploymentManager deploymentManager = CommandContextUtil.getProcessEngineConfiguration().getDeploymentManager();
// This will check the cache in the findDeployedProcessDefinitionById and resolveProcessDefinition method
ProcessDefinition processDefinitionEntity = deploymentManager.findDeployedProcessDefinitionById(processDefinitionId);
return deploymentManager.resolveProcessDefinition(processDefinitionEntity).getProcess();
}
}
public static BpmnModel getBpmnModel(String processDefinitionId) {
if (CommandContextUtil.getProcessEngineConfiguration() == null) {
return Flowable5Util.getFlowable5CompatibilityHandler().getProcessDefinitionBpmnModel(processDefinitionId);
} else {View on GitHub (pinned to d6d39ce1c6)