alibaba/spring-ai-alibaba · error · RuntimeException

Failed to restart shell session

Error message

Failed to restart shell session

What it means

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.

Source

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

				try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getErrorStream()))) {
					String line;
					while ((line = reader.readLine()) != null) {
						outputQueue.offer(new OutputLine("stderr", line));
					}
				} catch (IOException e) {
					log.debug("Stderr reader terminated", e);
				} finally {
					outputQueue.offer(new OutputLine("stderr", null)); // EOF marker
				}
			}, "shell-stderr-reader").start();
		}

		void restart() {
			stop(this.terminationTimeout);
			try {
				start();
			} catch (IOException e) {
				throw new RuntimeException("Failed to restart shell session", e);
			}
		}

		void stop(long timeoutMs) {
			if (process == null || !process.isAlive()) {
				return;
			}

			terminated = true;
			try {
				stdin.write("exit\n");
				stdin.flush();
			} catch (IOException e) {
				log.debug("Failed to send exit command", e);
			}

			try {
				if (!process.waitFor(timeoutMs, TimeUnit.MILLISECONDS)) {

View on GitHub (pinned to f82da0b50f)

Solutions

  1. Read getCause() (the IOException) to see why the process could not start, and verify the shell binary still exists at the configured path.
  2. Recreate the workspace directory if it was deleted, and check write permissions for the JVM user.
  3. Check OS limits (ulimit, cgroup pid limits) if process spawning fails under load; then retry the restart.
  4. As a fallback, discard the session entirely and call initialize(config) to build a brand-new session.

Example fix

// before
try { manager.restartSession(config); } catch (Exception e) { log.error("restart failed", e); }

// after
try { manager.restartSession(config); }
catch (RuntimeException e) {
    log.warn("restart failed, reinitializing", e);
    manager.initialize(config); // full fresh session as fallback
}
Defensive patterns

Strategy: retry

Validate before calling

// Verify environment can spawn a shell before restart:
if (!new File(shellBinary).canExecute()) throw new IllegalStateException("Shell missing: " + shellBinary);
if (!Files.isDirectory(workspace)) throw new IllegalStateException("Workspace gone: " + workspace);

Try / catch

try {
    manager.restartSession(config);
} catch (RuntimeException e) {
    // cause is IOException from process start — fall back to full re-init
    manager.initialize(config);
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


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