apache/dolphinscheduler · error · TaskException
Remote shell task error, exitStatus: ${exitStatus} error mes
Error message
Remote shell task error, exitStatus: ${exitStatus} error message: ${stderr} What it means
After running a remote command with output line processing, RemoteExecutor.runRemoteAndProcessLines checks the channel's exit status; if it is null (no exit status reported) or non-zero, it throws TaskException including the exitStatus and the captured stderr. This is the remote command itself failing — analogous to a local shell returning non-zero.
Source
Thrown at dolphinscheduler-task-plugin/dolphinscheduler-task-remoteshell/src/main/java/org/apache/dolphinscheduler/plugin/task/remoteshell/RemoteExecutor.java:257
ByteArrayOutputStream err = new ByteArrayOutputStream()) {
channel.setOut(out);
channel.setErr(err);
channel.open();
channel.waitFor(EnumSet.of(ClientChannelEvent.CLOSED), 0);
int readLines = 0;
try (
BufferedReader reader = new BufferedReader(
new InputStreamReader(new ByteArrayInputStream(out.toByteArray()),
StandardCharsets.UTF_8))) {
String line;
while ((line = reader.readLine()) != null) {
readLines++;
lineConsumer.accept(line);
}
}
Integer exitStatus = channel.getExitStatus();
if (exitStatus == null || exitStatus != 0) {
throw new TaskException(
"Remote shell task error, exitStatus: " + exitStatus + " error message: "
+ new String(err.toByteArray(), StandardCharsets.UTF_8));
}
return readLines;
}
}
private String getRemoteShellHome() {
return String.format(REMOTE_SHELL_HOME, sshConnectionParam.getUser());
}
@SneakyThrows
@Override
public void close() {
if (session != null && session.isOpen()) {
session.close();
}
if (sshClient != null && sshClient.isStarted()) {View on GitHub (pinned to 02eac45a1b)
Solutions
- Read the stderr text in the exception message — it usually contains the exact remote command error.
- Re-run the failing command manually over SSH to reproduce and debug the remote failure.
- Check the script for 'command not found' / path issues and that it exits 0 on success.
- If exitStatus is null, inspect whether the remote process was killed (OOM, signal) before completion.
- Make the script fail fast with 'set -e' so the failing line is evident in stderr.
Example fix
// before: script may fail with confusing exit code
#!/bin/bash
python app.py
// after
#!/bin/bash
set -e
python app.py || { echo "app.py failed"; exit 1; } Defensive patterns
Strategy: validation
Validate before calling
// validate the script locally first bash -n script.sh # syntax check shellcheck script.sh
Try / catch
try {
remoteExecutor.runRemote(cmd);
} catch (TaskException e) {
// message contains exitStatus and stderr
String msg = e.getMessage();
if (msg.contains("exitStatus: null")) logger.error("Remote process killed before exit status");
logger.error("Remote command failed: {}", msg);
} Prevention
- Use 'set -e' in remote scripts so failures surface early with clear stderr.
- Echo the failing command/step to stderr in long scripts for debuggability.
- Quote remote paths and validate them exist before executing.
When it happens
Trigger: runRemote() or readLines() executes a remote command whose channel.getExitStatus() is null or != 0 after the channel closes; the stderr buffer content is embedded in the message.
Common situations: The remote shell script has a bug (syntax error, command not found, non-zero exit); the remote path in the command is wrong; the script's exit code is non-zero due to application logic; SSH channel closed before exit status was delivered.
Related errors
AI-assisted analysis of apache/dolphinscheduler@02eac45a1b (2026-09-06).
Data as JSON: /api/errors/b0b6b244e2e665c8.
Report an issue: GitHub.