alibaba/spring-ai-alibaba · error · IllegalArgumentException
ShellSessionManager cannot be null
Error message
ShellSessionManager cannot be null
What it means
Identical guard to ShellTool: ShellTool2's constructor requires a non-null ShellSessionManager and throws this IllegalArgumentException when null is passed. ShellTool2 is the second-generation variant of the shell tool, and all of its shell operations depend on this manager.
Solutions
- Create and pass a fully configured ShellSessionManager to the ShellTool2 constructor.
- Fix the factory/builder that returned null (missing required configuration for the shell feature).
- In Spring, inject the manager as a required dependency so startup fails fast instead of passing null at runtime.
- Guard with Objects.requireNonNull at the construction site for an earlier, clearer failure.
Example fix
// before @Autowired(required = false) private ShellSessionManager sessionManager; ShellTool2 tool = new ShellTool2(sessionManager); // null if bean absent // after @Autowired private ShellSessionManager sessionManager; // required bean ShellTool2 tool = new ShellTool2(sessionManager);
Defensive patterns
Strategy: validation
Validate before calling
if (sessionManager == null) {
throw new IllegalStateException("ShellSessionManager must be built before constructing ShellTool2");
}
ShellTool2 tool = new ShellTool2(sessionManager); Try / catch
try {
ShellTool2 tool = new ShellTool2(sessionManager);
} catch (IllegalArgumentException e) {
if (e.getMessage().contains("cannot be null")) {
// build/lookup a valid ShellSessionManager before retrying
}
} Prevention
- Wire the manager as a required dependency when migrating from ShellTool to ShellTool2.
- Avoid @Autowired(required=false) for ShellSessionManager; prefer required constructor injection.
- Verify the shell feature is enabled in configuration so the manager bean is actually created.
- Add a null assertion at the wiring layer before tool construction.
When it happens
Trigger: Calling new ShellTool2(null) — usually because the manager came from a conditional factory, an optional Spring injection point, or a variable assigned later in the code path.
Common situations: Migrating from ShellTool to ShellTool2 and wiring the new tool before the manager bean exists; @Autowired(required=false) leaving the field null in tests; configuration disabled the shell feature so the manager was never created.
Related errors
- ShellSessionManager cannot be null
- Agent name cannot be null or empty
- ChatClient is required
- ChatClient must not be null
- Code must not be null
AI-assisted analysis of alibaba/spring-ai-alibaba@f82da0b50f (2026-09-09).
Data as JSON: /api/errors/2e07d66531e1f4c7.
Report an issue: GitHub.
Appendix: source
Thrown at spring-ai-alibaba-agent-framework/src/main/java/com/alibaba/cloud/ai/graph/agent/tools/ShellTool2.java:70
public static final String DEFAULT_TOOL_DESCRIPTION =
"Execute a shell command inside a persistent session. Before running a command, "
+ "confirm the working directory is correct (e.g., inspect with `ls` or `pwd`) and ensure "
+ "any parent directories exist. Prefer absolute paths and quote paths containing spaces, "
+ "such as `cd \"/path/with spaces\"`. Chain multiple commands with `&&` or `;` instead of "
+ "embedding newlines. Avoid unnecessary `cd` usage unless explicitly required so the "
+ "session remains stable. Outputs may be truncated when they become very large, and long "
+ "running commands will be terminated once their configured timeout elapses.";
private final ShellSessionManager sessionManager;
/**
* Constructs a new ShellTool2.
*
* @param sessionManager The manager for the shell session. Must not be null.
*/
public ShellTool2(ShellSessionManager sessionManager) {
if (sessionManager == null) {
throw new IllegalArgumentException("ShellSessionManager cannot be null");
}
this.sessionManager = sessionManager;
}
// @formatter:off
@Tool(name = "shell", description = DEFAULT_TOOL_DESCRIPTION)
public String executeShellCommand(
@ToolParam(description = "The command to execute in the shell.") String command,
@ToolParam(description = "Restart the shell session before executing the command (default: false).", required = false) Boolean restart,
ToolContext toolContext) { // @formatter:on
try {
RunnableConfig config = (RunnableConfig) toolContext.getContext().get(AGENT_CONFIG_CONTEXT_KEY);
// Handle restart request
if (Boolean.TRUE.equals(restart)) {
log.info("Restarting shell session as requested.");
sessionManager.restartSession(config);View on GitHub (pinned to f82da0b50f)