{"record":{"id":"cb29cff59d97d5e0","repo":"alibaba/spring-ai-alibaba","slug":"failed-to-restart-shell-session","errorCode":null,"errorMessage":"Failed to restart shell session","messagePattern":"Failed to restart shell session","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":436,"sourceCode":"\t\t\t\ttry (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getErrorStream()))) {\n\t\t\t\t\tString line;\n\t\t\t\t\twhile ((line = reader.readLine()) != null) {\n\t\t\t\t\t\toutputQueue.offer(new OutputLine(\"stderr\", line));\n\t\t\t\t\t}\n\t\t\t\t} catch (IOException e) {\n\t\t\t\t\tlog.debug(\"Stderr reader terminated\", e);\n\t\t\t\t} finally {\n\t\t\t\t\toutputQueue.offer(new OutputLine(\"stderr\", null)); // EOF marker\n\t\t\t\t}\n\t\t\t}, \"shell-stderr-reader\").start();\n\t\t}\n\n\t\tvoid restart() {\n\t\t\tstop(this.terminationTimeout);\n\t\t\ttry {\n\t\t\t\tstart();\n\t\t\t} catch (IOException e) {\n\t\t\t\tthrow new RuntimeException(\"Failed to restart shell session\", e);\n\t\t\t}\n\t\t}\n\n\t\tvoid stop(long timeoutMs) {\n\t\t\tif (process == null || !process.isAlive()) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tterminated = true;\n\t\t\ttry {\n\t\t\t\tstdin.write(\"exit\\n\");\n\t\t\t\tstdin.flush();\n\t\t\t} catch (IOException e) {\n\t\t\t\tlog.debug(\"Failed to send exit command\", e);\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tif (!process.waitFor(timeoutMs, TimeUnit.MILLISECONDS)) {","sourceCodeStart":418,"sourceCodeEnd":454,"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#L418-L454","documentation":"ShellSession.restart() stops the underlying OS process (waiting up to terminationTimeout) and then calls start() to spawn a fresh shell process. If start() throws an IOException (process cannot be spawned), restart() wraps it in this RuntimeException. Callers like restartSession() and collectOutput() hit this when the shell cannot be relaunched.","triggerScenarios":"restartSession() or an internal recovery path triggers session.restart(), and the subsequent process start fails with IOException — e.g. the shell executable is missing, the workspace directory was deleted, or OS resource limits block spawning a new process.","commonSituations":"Container image lacking the shell binary after a restart; workspace temp directory cleaned up between runs; fork failures under memory/pid pressure (ulimit -u); shell binary path changed after an environment update.","solutions":["Read getCause() (the IOException) to see why the process could not start, and verify the shell binary still exists at the configured path.","Recreate the workspace directory if it was deleted, and check write permissions for the JVM user.","Check OS limits (ulimit, cgroup pid limits) if process spawning fails under load; then retry the restart.","As a fallback, discard the session entirely and call initialize(config) to build a brand-new session."],"exampleFix":"// before\ntry { manager.restartSession(config); } catch (Exception e) { log.error(\"restart failed\", e); }\n\n// after\ntry { manager.restartSession(config); }\ncatch (RuntimeException e) {\n    log.warn(\"restart failed, reinitializing\", e);\n    manager.initialize(config); // full fresh session as fallback\n}","handlingStrategy":"retry","validationCode":"// Verify environment can spawn a shell before restart:\nif (!new File(shellBinary).canExecute()) throw new IllegalStateException(\"Shell missing: \" + shellBinary);\nif (!Files.isDirectory(workspace)) throw new IllegalStateException(\"Workspace gone: \" + workspace);","typeGuard":null,"tryCatchPattern":"try {\n    manager.restartSession(config);\n} catch (RuntimeException e) {\n    // cause is IOException from process start — fall back to full re-init\n    manager.initialize(config);\n}","preventionTips":["Keep the shell binary and workspace intact for the lifetime of the session.","Check container/OS process limits (ulimit -u, cgroup pids) under load.","Prefer full initialize() over restart() after environmental changes (image updates, moved workspace).","Log and inspect the wrapped IOException cause to identify spawn failures quickly."],"tags":["shell","process","restart","io"],"backgroundTag":"shell-session-restart-failed","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"}