{"record":{"id":"f4acd1c1febe4b42","repo":"alibaba/spring-ai-alibaba","slug":"failed-to-execute-command","errorCode":null,"errorMessage":"Failed to execute command","messagePattern":"Failed to execute command","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"spring-ai-alibaba-agent-framework/src/main/java/com/alibaba/cloud/ai/graph/agent/tools/ShellSessionManager.java","lineNumber":512,"sourceCode":"\t\t\t\t\t\t\t\t\t+ \"if ($__lcSucceeded) { $__lcExitCode = 0 } \"\n\t\t\t\t\t\t\t\t\t+ \"elseif ($null -ne $__lcNativeExit) { $__lcExitCode = $__lcNativeExit } \"\n\t\t\t\t\t\t\t\t\t+ \"else { $__lcExitCode = 1 }; \"\n\t\t\t\t\t\t\t\t\t+ \"Write-Output \\\"%s $__lcExitCode\\\"\\n\",\n\t\t\t\t\t\t\tmarker));\n\t\t\t\t} else if (isWindows) {\n\t\t\t\t\t// Windows cmd.exe: use ERRORLEVEL\n\t\t\t\t\tstdin.write(String.format(\"echo %s %%ERRORLEVEL%%\\n\", marker));\n\t\t\t\t} else {\n\t\t\t\t\t// Unix/Linux: use $? for exit code\n\t\t\t\t\tstdin.write(String.format(\"printf '%s %%s\\\\n' $?\\n\", marker));\n\t\t\t\t}\n\t\t\t\tstdin.flush();\n\n\t\t\t\t// Collect output\n\t\t\t\treturn collectOutput(marker, deadline, maxOutputLines, maxOutputBytes);\n\n\t\t\t} catch (IOException e) {\n\t\t\t\tthrow new RuntimeException(\"Failed to execute command\", e);\n\t\t\t}\n\t\t}\n\n\t\tprivate CommandResult collectOutput(String marker, long deadline, int maxOutputLines, Long maxOutputBytes) {\n\t\t\tList<String> lines = new ArrayList<>();\n\t\t\tint totalLines = 0;\n\t\t\tlong totalBytes = 0;\n\t\t\tboolean truncatedByLines = false;\n\t\t\tboolean truncatedByBytes = false;\n\t\t\tInteger exitCode = null;\n\t\t\tboolean timedOut = false;\n\n\t\t\twhile (true) {\n\t\t\t\tlong remaining = deadline - System.currentTimeMillis();\n\t\t\t\tif (remaining <= 0) {\n\t\t\t\t\ttimedOut = true;\n\t\t\t\t\tlog.warn(\"Command timed out, restarting session\");\n\t\t\t\t\trestart();","sourceCodeStart":494,"sourceCodeEnd":530,"githubUrl":"https://github.com/alibaba/spring-ai-alibaba/blob/f82da0b50f35744c13968191be2b1cd2452ef550/spring-ai-alibaba-agent-framework/src/main/java/com/alibaba/cloud/ai/graph/agent/tools/ShellSessionManager.java#L494-L530","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Catch RuntimeException with an IOException cause and restart the session (session.restart() / initialize()) before retrying the command.","Check whether the command itself can terminate the shell process and isolate it (subshell, nohup, separate process).","Verify the runtime environment kept the container/JVM and process alive for the command duration (timeout < container lifetime).","If it happens under heavy output volume, reduce maxOutputLines/maxOutputBytes or increase OS pipe buffers / drain output faster."],"exampleFix":"// before\nCommandResult r = session.execute(cmd, timeout, maxLines, maxBytes);\n\n// after\ntry {\n    CommandResult r = session.execute(cmd, timeout, maxLines, maxBytes);\n} catch (RuntimeException e) {\n    session.restart();\n    CommandResult r = session.execute(cmd, timeout, maxLines, maxBytes); // retry on fresh process\n}","handlingStrategy":"retry","validationCode":"// Pre-check and wrap risky commands so they cannot kill the shell:\nString safe = \"(\" + cmd + \")\"; // run in subshell\nif (!session.isAlive()) session.restart();","typeGuard":null,"tryCatchPattern":"try {\n    result = session.execute(cmd, timeout, maxLines, maxBytes);\n} catch (RuntimeException e) {\n    if (e.getCause() instanceof IOException) { // broken pipe / process died\n        session.restart();\n        result = session.execute(cmd, timeout, maxLines, maxBytes);\n    }\n}","preventionTips":["Run untrusted/heavy commands in a subshell so they cannot terminate the parent shell process.","Bound maxOutputLines/maxOutputBytes so output collection does not stall on dead pipes.","Keep command timeouts shorter than container/JVM lifetimes.","Implement restart-and-retry once for RuntimeException-with-IOException around execute()."],"tags":["shell","io","broken-pipe","process"],"backgroundTag":"broken-pipe","analyzedSha":"f82da0b50f35744c13968191be2b1cd2452ef550","analyzedAt":"2026-09-09T15:32:42.421Z","contentChangedAt":"2026-09-09T15:32:42.421Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}