{"record":{"id":"c4b2f06962fe2800","repo":"alibaba/spring-ai-alibaba","slug":"skill-not-found-c4b2f0","errorCode":null,"errorMessage":"Skill not found: {}","messagePattern":"Skill not found: (.+?)","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"spring-ai-alibaba-graph-core/src/main/java/com/alibaba/cloud/ai/graph/skills/registry/filesystem/FileSystemSkillRegistry.java","lineNumber":241,"sourceCode":"\t * Get the user skills directory path.\n\t * This is an implementation-specific method, not part of the SkillRegistry interface.\n\t *\n\t * @return the user skills directory path\n\t */\n\tpublic String getUserSkillsDirectory() {\n\t\treturn userSkillsDirectory;\n\t}\n\n\t@Override\n\tpublic String readSkillContent(String name) throws IOException {\n\t\tif (name == null || name.isEmpty()) {\n\t\t\tthrow new IllegalArgumentException(\"Skill name cannot be null or empty\");\n\t\t}\n\n\t\t// Get the skill by name\n\t\tOptional<SkillMetadata> skillOpt = get(name);\n\t\tif (skillOpt.isEmpty()) {\n\t\t\tthrow new IllegalStateException(\"Skill not found: \" + name);\n\t\t}\n\n\t\tSkillMetadata skill = skillOpt.get();\n\n\t\t// Use the normal loadFullContent method for filesystem skills\n\t\treturn skill.loadFullContent();\n\t}\n\n\t@Override\n\tpublic String getSkillLoadInstructions() {\n\t\tList<SkillMetadata> skills = listAll();\n\t\tList<SkillMetadata> userSkills = new ArrayList<>();\n\t\tList<SkillMetadata> projectSkills = new ArrayList<>();\n\t\tfor (SkillMetadata skill : skills) {\n\t\t\tif (\"project\".equals(skill.getSource())) {\n\t\t\t\tprojectSkills.add(skill);\n\t\t\t}\n\t\t\telse {","sourceCodeStart":223,"sourceCodeEnd":259,"githubUrl":"https://github.com/alibaba/spring-ai-alibaba/blob/f82da0b50f35744c13968191be2b1cd2452ef550/spring-ai-alibaba-graph-core/src/main/java/com/alibaba/cloud/ai/graph/skills/registry/filesystem/FileSystemSkillRegistry.java#L223-L259","documentation":"readSkillContent throws IllegalStateException when get(name) finds no skill matching the given name in the registry. Unlike a normal lookup API that returns Optional, this read API treats a missing skill as an exceptional state because the caller explicitly asked for one skill's full content.","triggerScenarios":"Calling readSkillContent with a name that is not registered: typo in skill name, skill directory absent from the configured skills directories, skill disabled/hidden and filtered out by the registry, or registry not initialized/loaded before the call.","commonSituations":"Renaming a skill directory but not the referencing code; passing a skill description or path instead of the skill name; skills directory misconfigured (wrong path) so the skill was never loaded; calling before auto-load of skills completes.","solutions":["Verify the exact skill name via registry.list()/search before reading","Check the configured user/project skills directories contain the skill","Ensure the registry is initialized and skills are loaded before reading"],"exampleFix":"// before\nString content = registry.readSkillContent(\"code-review\");\n// after\nif (registry.get(\"code-review\").isPresent()) {\n    String content = registry.readSkillContent(\"code-review\");\n} else {\n    // handle missing skill\n}","handlingStrategy":"try-catch","validationCode":"if (name != null && registry.get(name).isPresent()) { /* safe to read */ }","typeGuard":null,"tryCatchPattern":"try { content = registry.readSkillContent(name); } catch (IllegalStateException e) { log.warn(\"Skill missing: {}\", name); return null; }","preventionTips":["Check registry.get(name).isPresent() before reading","List available skills to verify exact spelling","Ensure skills directories are configured and loaded before reads"],"tags":["java","skills","not-found","registry"],"backgroundTag":"resource-not-found","analyzedSha":"f82da0b50f35744c13968191be2b1cd2452ef550","analyzedAt":"2026-09-09T15:32:42.421Z","contentChangedAt":"2026-09-09T15:32:42.421Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}