alibaba/spring-ai-alibaba · error · IllegalStateException

Shell session not initialized. Cannot restart a session that

Error message

Shell session not initialized. Cannot restart a session that does not exist.

What it means

restartSession() looks up the existing ShellSession in the run context and, failing that, in the global registry (HITL resume). If no session exists in either place, it throws this IllegalStateException: there is nothing to restart. Restart is defined as stopping and re-starting an existing OS process, so it requires a live session object.

Source

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

		return new CommandResult(output, result.getExitCode(), result.isTimedOut(),
			result.isTruncatedByLines(), result.isTruncatedByBytes(),
			result.getTotalLines(), result.getTotalBytes(), allMatches);
	}

	/**
	 * Restart the shell session.
	 * <p>If the session is missing from the context (e.g. after HITL resume),
	 * it will first attempt to recover from the global registry.</p>
	 */
	public void restartSession(RunnableConfig config) {
		ShellSession session = (ShellSession) config.context().get(SESSION_INSTANCE_CONTEXT_KEY);
		if (session == null) {
			// Try to recover from global registry (HITL resume scenario)
			session = recoverSessionFromRegistry(config);
		}
		if (session == null) {
			throw new IllegalStateException("Shell session not initialized. " +
					"Cannot restart a session that does not exist.");
		}

		log.info("Restarting shell session");
		session.restart();

		// Re-run startup commands
		for (String command : startupCommands) {
			session.execute(command, startupTimeout, maxOutputLines, maxOutputBytes);
		}
	}

	public int getMaxOutputLines() {
		return maxOutputLines;
	}

	/**
	 * Clear the global session registry. Package-private for test isolation.

View on GitHub (pinned to f82da0b50f)

Solutions

  1. Call initialize(config) first (fresh session) when you know no session exists, instead of restartSession().
  2. Confirm the threadId and context passed to restartSession() match those used at initialize().
  3. Check whether cleanup() already ran; after cleanup you must re-initialize rather than restart.
  4. Catch IllegalStateException and fall back to initialize() + retry as a recovery path.

Example fix

// before
if (manager.findSession(threadId) == null) { manager.restartSession(config); } // throws

// after
if (manager.findSession(threadId) == null) { manager.initialize(config); } else { manager.restartSession(config); }
Defensive patterns

Strategy: try-catch

Validate before calling

// Only restart when a session actually exists:
Object session = config.context().get("SHELL_SESSION_KEY");
if (session == null) manager.initialize(config); else manager.restartSession(config);

Try / catch

try {
    manager.restartSession(config);
} catch (IllegalStateException e) {
    if (e.getMessage().contains("does not exist")) {
        manager.initialize(config); // nothing to restart — create fresh
    }
}

Prevention

When it happens

Trigger: Calling restartSession() before initialize() was ever called for the threadId, after the context was cleared and the global registry entry was removed (e.g. cleanup already ran), or with a mismatched threadId/context so the lookup misses.

Common situations: Recovering after a JVM restart where the in-memory registry is empty; calling restartSession() on a brand-new manager; threadId typo so the registry lookup finds nothing; double-cleanup followed by a restart attempt.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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