flowable/flowable-engine · error · ActivitiException
Could not execute shell command
Error message
Could not execute shell command
What it means
Thrown by ShellActivityBehavior.execute when any exception occurs while running the configured external shell command (process start, I/O, interruption, etc.). The original exception is wrapped as the cause, so the root reason is in the stack trace. It signals that the BPMN shell task could not run the command to completion.
Solutions
- Inspect the wrapped cause (e.getCause()) in the stack trace to find the real failure (IOException: Cannot run program ... is usually command-not-found).
- Verify the 'command' attribute/expression of the shell task resolves to an executable that exists on the machine running the engine, using an absolute path if necessary.
- Check that arg/input/output/errorCode variable expressions resolve to non-null values of the expected types at execution time.
- Ensure the engine's OS user has execute permission on the binary and the environment (PATH, container image) contains required tools.
- Wrap or configure the shell task so failures are handled by a boundary error event or try alternative execution.
- Example fix
Example fix
// before
<serviceTask id="runScript" activiti:type="shell">
<extensionElements>
<activiti:field name="command" stringValue="my-script.sh"/>
</extensionElements>
</serviceTask>
// after
<serviceTask id="runScript" activiti:type="shell">
<extensionElements>
<activiti:field name="command" stringValue="/opt/scripts/my-script.sh"/>
<activiti:field name="arg1" expression="${requiredParam}"/>
</extensionElements>
</serviceTask> Defensive patterns
Strategy: try-catch
Validate before calling
// before executing the process / shell task
String cmd = (String) runtimeService.getVariable(executionId, "command");
if (cmd == null || !new File(cmd).canExecute()) {
throw new IllegalStateException("Shell command not executable on engine host: " + cmd);
} Try / catch
try {
taskService.complete(taskId, vars);
} catch (ActivitiException e) {
log.error("Shell task failed; root cause: ", e.getCause());
if (e.getCause() instanceof IOException) { /* command missing/unexecutable */ }
throw new CommandExecutionException(e.getCause());
} Prevention
- Use absolute paths for shell commands in BPMN shell tasks.
- Verify the command exists and is executable on every environment where the engine runs (containers included).
- Ensure all arg/input variable expressions are non-null before reaching the task.
- Capture and log stderr/stdout fields so failures are diagnosable.
- Consider handling failures via BPMN error boundary events instead of failing the whole transaction.
When it happens
Trigger: A service task of type 'shell' executes and RuntimeExec/ProcessBuilder fails: the command binary does not exist, arg/input/output variable expressions resolve to null or bad types, the process writes too much output and blocks, or waitFor is interrupted. Any Exception in the try block is converted to ActivitiException here.
Common situations: Command path not present on the server/PATH of the engine host; missing execute permissions; arguments built from process variables that are unset at runtime; timeouts/interruptions; running in a container without the needed CLI tools.
Related errors
- Could not execute shell command for + execution
- Activity needed for multi instance cannot bv found
- multiple none start events or timer start events not…
- The default BPMN parse handlers should only support one…
- activity tenant id is null
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/272150dec107f798.
Report an issue: GitHub.
Appendix: source
Thrown at modules/flowable5-engine/src/main/java/org/activiti/engine/impl/bpmn/behavior/ShellActivityBehavior.java:130
Process process = processBuilder.start();
if (waitFlag) {
int errorCode = process.waitFor();
if (resultVariableStr != null) {
String result = convertStreamToStr(process.getInputStream());
execution.setVariable(resultVariableStr, result);
}
if (errorCodeVariableStr != null) {
execution.setVariable(errorCodeVariableStr, Integer.toString(errorCode));
}
}
} catch (Exception e) {
throw new ActivitiException("Could not execute shell command ", e);
}
leave(activityExecution);
}
public static String convertStreamToStr(InputStream is) throws IOException {
if (is != null) {
Writer writer = new StringWriter();
char[] buffer = new char[1024];
try {
Reader reader = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8));
int n;
while ((n = reader.read(buffer)) != -1) {
writer.write(buffer, 0, n);
}
} finally {
View on GitHub (pinned to d6d39ce1c6)