alibaba/spring-ai-alibaba · error · RuntimeException

Failed to execute command

Error message

Failed to execute command

What it means

Inside ShellSession.execute(), after writing the command and completion marker to the process stdin and flushing, any IOException (most commonly a broken pipe because the shell process died mid-command) is caught and rethrown as this RuntimeException. It indicates I/O to/from the shell process failed during command execution.

Source

Thrown at spring-ai-alibaba-agent-framework/src/main/java/com/alibaba/cloud/ai/graph/agent/tools/ShellSessionManager.java:512

									+ "if ($__lcSucceeded) { $__lcExitCode = 0 } "
									+ "elseif ($null -ne $__lcNativeExit) { $__lcExitCode = $__lcNativeExit } "
									+ "else { $__lcExitCode = 1 }; "
									+ "Write-Output \"%s $__lcExitCode\"\n",
							marker));
				} else if (isWindows) {
					// Windows cmd.exe: use ERRORLEVEL
					stdin.write(String.format("echo %s %%ERRORLEVEL%%\n", marker));
				} else {
					// Unix/Linux: use $? for exit code
					stdin.write(String.format("printf '%s %%s\\n' $?\n", marker));
				}
				stdin.flush();

				// Collect output
				return collectOutput(marker, deadline, maxOutputLines, maxOutputBytes);

			} catch (IOException e) {
				throw new RuntimeException("Failed to execute command", e);
			}
		}

		private CommandResult collectOutput(String marker, long deadline, int maxOutputLines, Long maxOutputBytes) {
			List<String> lines = new ArrayList<>();
			int totalLines = 0;
			long totalBytes = 0;
			boolean truncatedByLines = false;
			boolean truncatedByBytes = false;
			Integer exitCode = null;
			boolean timedOut = false;

			while (true) {
				long remaining = deadline - System.currentTimeMillis();
				if (remaining <= 0) {
					timedOut = true;
					log.warn("Command timed out, restarting session");
					restart();

View on GitHub (pinned to f82da0b50f)

Solutions

  1. Catch RuntimeException with an IOException cause and restart the session (session.restart() / initialize()) before retrying the command.
  2. Check whether the command itself can terminate the shell process and isolate it (subshell, nohup, separate process).
  3. Verify the runtime environment kept the container/JVM and process alive for the command duration (timeout < container lifetime).
  4. If it happens under heavy output volume, reduce maxOutputLines/maxOutputBytes or increase OS pipe buffers / drain output faster.

Example fix

// before
CommandResult r = session.execute(cmd, timeout, maxLines, maxBytes);

// after
try {
    CommandResult r = session.execute(cmd, timeout, maxLines, maxBytes);
} catch (RuntimeException e) {
    session.restart();
    CommandResult r = session.execute(cmd, timeout, maxLines, maxBytes); // retry on fresh process
}
Defensive patterns

Strategy: retry

Validate before calling

// Pre-check and wrap risky commands so they cannot kill the shell:
String safe = "(" + cmd + ")"; // run in subshell
if (!session.isAlive()) session.restart();

Try / catch

try {
    result = session.execute(cmd, timeout, maxLines, maxBytes);
} catch (RuntimeException e) {
    if (e.getCause() instanceof IOException) { // broken pipe / process died
        session.restart();
        result = session.execute(cmd, timeout, maxLines, maxBytes);
    }
}

Prevention

When it happens

Trigger: Writing the command or marker to the process stdin fails with IOException — the shell process exited between the liveness check and the write, the pipe was closed by the OS, or output streaming hit an I/O error while collecting output up to the deadline.

Common situations: Command kills the shell mid-execution (OOM-killed, 'kill $$', crash); OS closed the pipe after the process died; very long output combined with process death during collectOutput; container stopped while a command was running.

Related errors


AI-assisted analysis of alibaba/spring-ai-alibaba@f82da0b50f (2026-09-09). Data as JSON: /api/errors/f4acd1c1febe4b42. Report an issue: GitHub.