alibaba/spring-ai-alibaba · error · IllegalArgumentException
Duplicate hook instances found
Error message
Duplicate hook instances found
What it means
ReactAgent.initGraph validates that all effective hooks (hooks from sub-agents plus this agent's own hooks) have unique full hook names, throwing IllegalArgumentException on the first duplicate. Duplicate hooks would cause the same lifecycle logic to run twice per node.
Solutions
- Remove the duplicate hook registration — register each hook at a single level of the agent hierarchy.
- If distinct behavior is needed, create a second Hook instance/class with a different full hook name.
- Deduplicate before build(): collect hooks into a Set keyed by Hook.getFullHookName(hook).
Example fix
// before builder.hooks(myInterceptor); subAgentBuilder.hooks(myInterceptor); // same instance propagates up // after builder.hooks(myInterceptor); // register only once, on the parent
Defensive patterns
Strategy: validation
Validate before calling
Set<String> seen = new HashSet<>();
for (Hook h : allHooks) {
if (!seen.add(Hook.getFullHookName(h)))
throw new IllegalArgumentException("Duplicate hook registered: " + Hook.getFullHookName(h));
} Try / catch
try { agent = builder.build(); } catch (IllegalArgumentException e) { if (e.getMessage().contains("Duplicate hook")) { log.error("Register each hook once; check nested agents sharing hook instances"); } throw e; } Prevention
- Register hooks at exactly one level of the agent hierarchy.
- Deduplicate hook lists with a Set keyed by getFullHookName before building.
- Avoid sharing one hook instance between parent and sub-agent builders.
When it happens
Trigger: Registering the same Hook instance (or two hooks sharing the same full hook name) more than once — e.g. an interceptor added to both a sub-agent and the parent so it appears twice in effectiveHooks when building the graph.
Common situations: Sharing one interceptor/hook object across nested agents in multi-agent setups; programmatically appending hooks that were already inherited from sub-agents.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Agent name must not be empty
- AgentScope Model must be provided for AgentScope routing…
- AgentScope routing flow requires agentScopeModel in config…
- AgentScope routing flow requires at least one sub-agent
- AgentScope routing flow requires root agent to be…
AI-assisted analysis of alibaba/spring-ai-alibaba@f82da0b50f (2026-09-09).
Data as JSON: /api/errors/43a78a89b225ee28.
Report an issue: GitHub.
Appendix: source
Thrown at spring-ai-alibaba-agent-framework/src/main/java/com/alibaba/cloud/ai/graph/agent/ReactAgent.java:326
}
@Override
protected StateGraph initGraph() throws GraphStateException {
if (hooks == null) {
hooks = new ArrayList<>();
}
// Always inject default InstructionAgentHook so instruction is handled in beforeAgent
List<Hook> effectiveHooks = new ArrayList<>();
effectiveHooks.add(InstructionAgentHook.create());
effectiveHooks.addAll(hooks);
// Validate hook uniqueness
Set<String> hookNames = new HashSet<>();
for (Hook hook : effectiveHooks) {
if (!hookNames.add(Hook.getFullHookName(hook))) {
throw new IllegalArgumentException("Duplicate hook instances found");
}
// set agent name to every hook node.
hook.setAgentName(this.name);
hook.setAgent(this);
}
// Create graph with state serializer
StateGraph graph = new StateGraph(name, buildMessagesKeyStrategyFactory(effectiveHooks), stateSerializer);
graph.addNode(AGENT_MODEL_NAME, node_async(this.llmNode));
if (hasTools) {
graph.addNode(AGENT_TOOL_NAME, node_async(this.toolNode));
}
// some hooks may need tools so they can do some initialization/cleanup on start/end of agent loop
setupToolsForHooks(effectiveHooks, toolNode);
View on GitHub (pinned to f82da0b50f)