alibaba/spring-ai-alibaba · warning

Shell session not found in context or registry for threadId

Error message

Shell session not found in context or registry for threadId {}. Creating new session for HITL recovery.

What it means

ShellSessionManager.executeCommand found no ShellSession stored in the tool context or session registry for the given threadId. When a threadId is present it logs this warning and auto-initializes a new session so that human-in-the-loop (HITL) resumed executions can continue; when no threadId is present it fails fast with IllegalStateException instead, since no lifecycle management would exist for the new process.

Source

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

	 * where a fresh {@link RunnableConfig} with an empty context is used), the method will:
	 * <ol>
	 *   <li>First attempt to recover the existing session from the global registry using threadId</li>
	 *   <li>If not found in registry, create a new session as fallback</li>
	 * </ol>
	 * This ensures shell state (working directory, environment variables) is preserved across HITL interrupts.</p>
	 */
	public CommandResult executeCommand(String command, RunnableConfig config) {
		ShellSession session = (ShellSession) config.context().get(SESSION_INSTANCE_CONTEXT_KEY);
		if (session == null) {
			// Try to recover from global registry using threadId
			session = recoverSessionFromRegistry(config);
			if (session == null) {
				// Only auto-initialize in the HITL recovery case (threadId present).
				// For truly uninitialized usage (no threadId), preserve the previous
				// behavior and fail fast rather than starting a new shell process
				// without lifecycle management.
				if (config.threadId().isPresent()) {
					log.warn("Shell session not found in context or registry for threadId {}. " +
							"Creating new session for HITL recovery.", config.threadId().get());
					initialize(config);
					session = (ShellSession) config.context().get(SESSION_INSTANCE_CONTEXT_KEY);
				}
				else {
					throw new IllegalStateException(
							"Shell session not initialized. Call initialize() before executeCommand() " +
									"or ensure lifecycle management (e.g., ShellToolAgentHook) is installed.");
				}
			}
		}

		log.info("Executing shell command: {}", command);
		CommandResult result = session.execute(command, commandTimeout, maxOutputLines, maxOutputBytes);

		// Apply redactions and track matches
		String output = result.getOutput();
		Map<String, List<String>> allMatches = new HashMap<>();

View on GitHub (pinned to f82da0b50f)

Solutions

  1. No action strictly needed: the manager auto-recovers by calling initialize(config) for HITL; verify the new session works and prior working directory/env expectations are re-applied.
  2. If sessions must survive restarts, persist session metadata (working dir, env) in graph state/checkpoints and re-initialize deterministically.
  3. Ensure the same threadId is used on resume so the registry lookup succeeds and recovery is not needed.
  4. If you hit this with NO threadId, that is a different failure (IllegalStateException): pass a threadId in the tool config.

Example fix

// before
String result = shellTool.executeCommand("ls", null);
// after
String result = shellTool.executeCommand("ls", "my-thread-123");
Defensive patterns

Strategy: validation

Validate before calling

if (threadId == null || threadId.isBlank()) throw new IllegalArgumentException("threadId required for shell tool usage with HITL resume");

Prevention

When it happens

Trigger: Calling executeCommand (directly or via the shell tool 'result' path) with a config whose threadId is set, but the process restarted or the context was rebuilt so the previously initialized session is gone from context/registry.

Common situations: Application restart between tool call and human approval (HITL flow), context map not propagated through graph checkpointing, calling the tool from a different thread than the one that initialized the session.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


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