alibaba/spring-ai-alibaba · error · IllegalArgumentException
SkillRegistry must be provided. Use FileSystemSkillRegistry.
Error message
SkillRegistry must be provided. Use FileSystemSkillRegistry.builder() to create one.
What it means
SkillsAgentHook's private Builder-based constructor requires builder.skillRegistry to be non-null. The hook wires together read/search/disable skill tools that all need the registry, so it refuses to build without one and points you at FileSystemSkillRegistry.builder() as the intended way to create it.
Source
Thrown at spring-ai-alibaba-agent-framework/src/main/java/com/alibaba/cloud/ai/graph/agent/hook/skills/SkillsAgentHook.java:93
* }</pre>
*/
@HookPositions(HookPosition.BEFORE_AGENT)
public class SkillsAgentHook extends AgentHook {
private static final Logger logger = LoggerFactory.getLogger(SkillsAgentHook.class);
private final SkillRegistry skillRegistry;
private final boolean autoReload;
private final Map<String, List<ToolCallback>> groupedTools;
private final Supplier<Map<String, List<ToolCallback>>> groupedToolsSupplier;
private final ToolCallbackResolver toolCallbackResolver;
private final ToolCallback readSkillTool;
private final ToolCallback searchSkillsTool;
private final ToolCallback disableSkillTool;
private SkillsAgentHook(Builder builder) {
if (builder.skillRegistry == null) {
throw new IllegalArgumentException("SkillRegistry must be provided. Use FileSystemSkillRegistry.builder() to create one.");
}
this.skillRegistry = builder.skillRegistry;
this.autoReload = builder.autoReload;
this.groupedTools = builder.groupedTools != null ? builder.groupedTools : Collections.emptyMap();
this.groupedToolsSupplier = builder.groupedToolsSupplier;
this.toolCallbackResolver = builder.toolCallbackResolver;
this.readSkillTool = ReadSkillTool.createReadSkillToolCallback(
this.skillRegistry,
ReadSkillTool.DESCRIPTION
);
this.searchSkillsTool = SearchSkillsTool.createSearchSkillsToolCallback(
this.skillRegistry,
SearchSkillsTool.DESCRIPTION
);
this.disableSkillTool = DisableSkillTool.createDisableSkillToolCallback(
this.skillRegistry,
DisableSkillTool.DESCRIPTION
);View on GitHub (pinned to f82da0b50f)
Solutions
- Add .skillRegistry(FileSystemSkillRegistry.builder().build()) to the builder chain before build().
- Point the FileSystemSkillRegistry builder at your skills directory and pass the result into the hook.
- If skills are optional, wrap hook creation in a check so it is only built when a registry is available.
Example fix
// before
SkillsAgentHook hook = SkillsAgentHook.builder().build();
// after
SkillsAgentHook hook = SkillsAgentHook.builder()
.skillRegistry(FileSystemSkillRegistry.builder().skillDirectory(skillsDir).build())
.build(); Defensive patterns
Strategy: validation
Validate before calling
SkillRegistry registry = FileSystemSkillRegistry.builder().skillDirectory(skillsDir).build(); SkillsAgentHook hook = SkillsAgentHook.builder().skillRegistry(registry).build();
Type guard
boolean hookReady(SkillsAgentHook.Builder b) { return b != null; } // set skillRegistry before build() Try / catch
try { hook = SkillsAgentHook.builder().skillRegistry(registry).build(); } catch (IllegalArgumentException e) { log.error("Skills hook disabled: {}", e.getMessage()); } Prevention
- Always chain .skillRegistry(...) before .build().
- Treat the registry as a mandatory prerequisite of the hook in your config class.
- Validate skillsDir exists at startup so the registry build itself cannot yield null.
When it happens
Trigger: Calling SkillsAgentHook.builder().build() without invoking .skillRegistry(...), or passing an explicitly null registry to the builder.
Common situations: Fluent-builder chains where the registry step was omitted; assuming the hook auto-creates a registry from a default directory (it does not); conditional config that nulls out the registry.
Understand the failure class
Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.
Related errors
- At least one limit must be specified (threadLimit or runLimi
- 参数 ${parameterName} 的值 ${value} 无法转换为类型 ${type}
- SubAgent name is required
- SubAgent description is required
- SubAgent system prompt is required
AI-assisted analysis of alibaba/spring-ai-alibaba@f82da0b50f (2026-09-09).
Data as JSON: /api/errors/b98c1f2b02a4fb0c.
Report an issue: GitHub.