{"record":{"id":"08f3738851c01b6b","repo":"alibaba/spring-ai-alibaba","slug":"shell-session-is-not-running","errorCode":null,"errorMessage":"Shell session is not running","messagePattern":"Shell session is not running","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"spring-ai-alibaba-agent-framework/src/main/java/com/alibaba/cloud/ai/graph/agent/tools/ShellSessionManager.java","lineNumber":471,"sourceCode":"\t\t\ttry {\n\t\t\t\tif (!process.waitFor(timeoutMs, TimeUnit.MILLISECONDS)) {\n\t\t\t\t\tprocess.destroyForcibly();\n\t\t\t\t}\n\t\t\t} catch (InterruptedException e) {\n\t\t\t\tThread.currentThread().interrupt();\n\t\t\t\tprocess.destroyForcibly();\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tstdin.close();\n\t\t\t} catch (IOException e) {\n\t\t\t\tlog.debug(\"Failed to close stdin\", e);\n\t\t\t}\n\t\t}\n\n\t\tsynchronized CommandResult execute(String command, long timeoutMs, int maxOutputLines, Long maxOutputBytes) {\n\t\t\tif (process == null || !process.isAlive()) {\n\t\t\t\tthrow new IllegalStateException(\"Shell session is not running\");\n\t\t\t}\n\n\t\t\tString marker = DONE_MARKER_PREFIX + UUID.randomUUID().toString().replace(\"-\", \"\");\n\t\t\tlong deadline = System.currentTimeMillis() + timeoutMs;\n\n\t\t\ttry {\n\t\t\t\t// Clear output queue\n\t\t\t\toutputQueue.clear();\n\n\t\t\t\t// Send command\n\t\t\t\tstdin.write(command);\n\t\t\t\tif (!command.endsWith(\"\\n\")) {\n\t\t\t\t\tstdin.write(\"\\n\");\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t// Send marker command based on shell type\n\t\t\t\tif (isPowerShell) {\n\t\t\t\t\t// PowerShell only sets $LASTEXITCODE for native programs and scripts. Capture","sourceCodeStart":453,"sourceCodeEnd":489,"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#L453-L489","documentation":"ShellSession.execute() first checks that the underlying process is non-null and alive; if the shell process has exited or was never started, it throws this IllegalStateException instead of writing to a dead process's stdin. It is the guard that keeps command execution tied to a live shell.","triggerScenarios":"Calling session.execute(command, ...) (directly or via executeCommand/startup commands) after the shell process died (e.g. a previous command called 'exit'), after stop()/restart() tore it down, or on a session object whose process was never started.","commonSituations":"The executed command itself terminated the shell ('exit', fatal crash, OOM kill); a long idle period where the OS reaped the process; concurrent stop() from another thread; using a stale session reference recovered from a registry after the process died.","solutions":["Catch IllegalStateException and call session.restart() (or manager.initialize()) to obtain a live process before retrying the command.","Check session/process liveness (isAlive) before each execute() and recover proactively.","Avoid running commands that can terminate the shell itself; run them detached (e.g. 'nohup ... &' or a subshell) if needed.","Ensure no concurrent thread calls stop()/cleanup() while other threads are executing commands (synchronize at the application level)."],"exampleFix":"// before\nCommandResult r = session.execute(cmd, timeout, maxLines, maxBytes); // throws if process died\n\n// after\nif (session == null || !session.isAlive()) { session.restart(); }\nCommandResult r = session.execute(cmd, timeout, maxLines, maxBytes);","handlingStrategy":"try-catch","validationCode":"// Liveness check before executing:\nif (session == null || !session.isAlive()) session.restart();","typeGuard":"boolean sessionAlive(ShellSession s) { return s != null && s.isAlive(); }","tryCatchPattern":"try {\n    result = session.execute(cmd, timeout, maxLines, maxBytes);\n} catch (IllegalStateException e) {\n    if (e.getMessage().contains(\"not running\")) {\n        session.restart();\n        result = session.execute(cmd, timeout, maxLines, maxBytes);\n    }\n}","preventionTips":["Check process liveness before each execute() call.","Never run commands that can kill the host shell ('exit', 'kill $$', fatal crashes); use subshells or nohup.","Avoid concurrent stop()/cleanup() while commands may be executing.","Treat long-idle sessions as suspect — restart proactively before reuse."],"tags":["shell","process","dead-process","illegal-state"],"backgroundTag":"invalid-state-transition","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"}