Activiti/Activiti · error · ActivitiException
Could not execute shell command
Error message
Could not execute shell command
What it means
A BPMN shell task (ShellActivityBehavior) failed to execute its configured shell command; Activiti wraps the failure in this ActivitiException. The cause carries the underlying error from the command executor.
Solutions
- Check the cause exception for the actual command failure (file not found, exit code, timeout)
- Verify the command exists in the runtime environment's PATH (docker exec which <cmd>)
- Review the shell task fields: command, arg1..argN, wait, timeout, outputVariable expressions
- Prefer a dedicated worker/REST call over shell tasks in containers; or install the required binary in the image
Example fix
<!-- before -->
<serviceTask id="sh" activiti:delegateExpression="${shellActivityBehavior}">
<extensionElements><activiti:field name="command" expression="ffmpeg"/></extensionElements>
<!-- after (image includes binary or use absolute path) -->
<extensionElements><activiti:field name="command" expression="/usr/local/bin/ffmpeg"/></extensionElements> Defensive patterns
Strategy: validation
Validate before calling
// before deploying a process with a shell task
String cmd = "ffmpeg";
if (Stream.of(System.getenv("PATH").split(File.pathSeparator))
.noneMatch(p -> new File(p, cmd).canExecute())) {
throw new IllegalStateException("Shell task command not available: " + cmd);
} Try / catch
try {
runtimeService.startProcessInstanceByKey("shellProc", vars);
} catch (ActivitiException e) {
if (e.getMessage().startsWith("Could not execute shell command")) {
log.error("Shell task failed: {}", e.getCause(), e);
}
throw e;
} Prevention
- Use absolute paths for shell task commands
- Verify required binaries exist in the deployment image/container
- Prefer service delegates/REST calls over shell tasks in containerized environments
- Set wait/timeout fields explicitly so hung commands fail predictably
When it happens
Trigger: Shell service task executes and ShellCommandExecutor.executeCommand() throws: command binary not found on PATH, working directory missing, timeout, non-zero/failed execution handling, or invalid shell task field configuration.
Common situations: Deploying a process with shell task to an environment lacking the command (e.g. curl/ffmpeg not installed in the container); wrong argument/timeout expressions; running under a user without execute permission; karg variables resolving to null.
Related errors
- _ACTIVITI_SKIP_EXPRESSION_ENABLED variable does not resolve…
- ' ' is not valid boolean in mapException with errorCode=…
- BPMN XSD could not be found
- Cannot create an event-throwing event-listener, unknown…
- Cannot start a sub process instance. Process model (id = )…
AI-assisted analysis of Activiti/Activiti@56435b1a97 (2026-09-09).
Data as JSON: /api/errors/31936c7366bb6e73.
Report an issue: GitHub.
Appendix: source
Thrown at activiti-core/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/behavior/ShellActivityBehavior.java:118
);
CommandExecutor commandExecutor = null;
CommandExecutorFactory shellCommandExecutorFactory = CommandExecutorContext.getShellCommandExecutorFactory();
if (shellCommandExecutorFactory != null) {
// if there is a ShellExecutorFactoryProvided
// then it will be used to create a desired shell command executor.
commandExecutor = shellCommandExecutorFactory.createExecutor(executorContext);
} else {
// default Shell executor (if the shell security is OFF)
commandExecutor = new ShellCommandExecutor(executorContext);
}
try {
commandExecutor.executeCommand(execution);
} catch (Exception e) {
throw new ActivitiException("Could not execute shell command ", e);
}
leave(execution);
}
protected String getStringFromField(Expression expression, DelegateExecution execution) {
if (expression != null) {
Object value = expression.getValue(execution);
if (value != null) {
return value.toString();
}
}
return null;
}
}
View on GitHub (pinned to 56435b1a97)