{"record":{"id":"b98c1f2b02a4fb0c","repo":"alibaba/spring-ai-alibaba","slug":"skillregistry-must-be-provided-use-filesystemskil","errorCode":null,"errorMessage":"SkillRegistry must be provided. Use FileSystemSkillRegistry.builder() to create one.","messagePattern":"SkillRegistry must be provided\\. Use FileSystemSkillRegistry\\.builder\\(\\) to create one\\.","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"spring-ai-alibaba-agent-framework/src/main/java/com/alibaba/cloud/ai/graph/agent/hook/skills/SkillsAgentHook.java","lineNumber":93,"sourceCode":" * }</pre>\n */\n@HookPositions(HookPosition.BEFORE_AGENT)\npublic class SkillsAgentHook extends AgentHook {\n\n\tprivate static final Logger logger = LoggerFactory.getLogger(SkillsAgentHook.class);\n\n\tprivate final SkillRegistry skillRegistry;\n\tprivate final boolean autoReload;\n\tprivate final Map<String, List<ToolCallback>> groupedTools;\n\tprivate final Supplier<Map<String, List<ToolCallback>>> groupedToolsSupplier;\n\tprivate final ToolCallbackResolver toolCallbackResolver;\n\tprivate final ToolCallback readSkillTool;\n\tprivate final ToolCallback searchSkillsTool;\n\tprivate final ToolCallback disableSkillTool;\n\n\tprivate SkillsAgentHook(Builder builder) {\n\t\tif (builder.skillRegistry == null) {\n\t\t\tthrow new IllegalArgumentException(\"SkillRegistry must be provided. Use FileSystemSkillRegistry.builder() to create one.\");\n\t\t}\n\t\tthis.skillRegistry = builder.skillRegistry;\n\t\tthis.autoReload = builder.autoReload;\n\t\tthis.groupedTools = builder.groupedTools != null ? builder.groupedTools : Collections.emptyMap();\n\t\tthis.groupedToolsSupplier = builder.groupedToolsSupplier;\n\t\tthis.toolCallbackResolver = builder.toolCallbackResolver;\n\t\tthis.readSkillTool = ReadSkillTool.createReadSkillToolCallback(\n\t\t\t\tthis.skillRegistry,\n\t\t\t\tReadSkillTool.DESCRIPTION\n\t\t);\n\t\tthis.searchSkillsTool = SearchSkillsTool.createSearchSkillsToolCallback(\n\t\t\t\tthis.skillRegistry,\n\t\t\t\tSearchSkillsTool.DESCRIPTION\n\t\t);\n\t\tthis.disableSkillTool = DisableSkillTool.createDisableSkillToolCallback(\n\t\t\t\tthis.skillRegistry,\n\t\t\t\tDisableSkillTool.DESCRIPTION\n\t\t);","sourceCodeStart":75,"sourceCodeEnd":111,"githubUrl":"https://github.com/alibaba/spring-ai-alibaba/blob/f82da0b50f35744c13968191be2b1cd2452ef550/spring-ai-alibaba-agent-framework/src/main/java/com/alibaba/cloud/ai/graph/agent/hook/skills/SkillsAgentHook.java#L75-L111","documentation":"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.","triggerScenarios":"Calling SkillsAgentHook.builder().build() without invoking .skillRegistry(...), or passing an explicitly null registry to the builder.","commonSituations":"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.","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."],"exampleFix":"// before\nSkillsAgentHook hook = SkillsAgentHook.builder().build();\n// after\nSkillsAgentHook hook = SkillsAgentHook.builder()\n    .skillRegistry(FileSystemSkillRegistry.builder().skillDirectory(skillsDir).build())\n    .build();","handlingStrategy":"validation","validationCode":"SkillRegistry registry = FileSystemSkillRegistry.builder().skillDirectory(skillsDir).build();\nSkillsAgentHook hook = SkillsAgentHook.builder().skillRegistry(registry).build();","typeGuard":"boolean hookReady(SkillsAgentHook.Builder b) { return b != null; } // set skillRegistry before build()","tryCatchPattern":"try { hook = SkillsAgentHook.builder().skillRegistry(registry).build(); } catch (IllegalArgumentException e) { log.error(\"Skills hook disabled: {}\", e.getMessage()); }","preventionTips":["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."],"tags":["java","builder-validation","configuration"],"backgroundTag":"missing-required-config-field","analyzedSha":"f82da0b50f35744c13968191be2b1cd2452ef550","analyzedAt":"2026-09-09T15:32:42.421Z","contentChangedAt":"2026-09-09T15:32:42.421Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}