{"record":{"id":"f7dbc0ebdb5d1426","repo":"alibaba/spring-ai-alibaba","slug":"skill-name-cannot-be-null-or-empty-f7dbc0","errorCode":null,"errorMessage":"Skill name cannot be null or empty","messagePattern":"Skill name cannot be null or empty","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"spring-ai-alibaba-graph-core/src/main/java/com/alibaba/cloud/ai/graph/skills/registry/filesystem/FileSystemSkillRegistry.java","lineNumber":235,"sourceCode":"\t */\n\tpublic String getProjectSkillsDirectory() {\n\t\treturn projectSkillsDirectory;\n\t}\n\n\t/**\n\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<>();","sourceCodeStart":217,"sourceCodeEnd":253,"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#L217-L253","documentation":"readSkillContent(name) rejects a null or empty skill name with IllegalArgumentException before attempting any lookup. The registry requires an explicit, non-empty identifier to resolve a skill on the filesystem, so blank names are treated as programmer error rather than a lookup miss.","triggerScenarios":"Calling readSkillContent(null), readSkillContent(\"\") directly, or indirectly when a caller (e.g. a test like disableHidesSkillFromReadsAndSearch or a tool/skill loader) passes a name sourced from an unset config property, empty map lookup, or uninitialized variable.","commonSituations":"Skill name loaded from YAML/config that is missing or empty; result of a search/filter that returned no name; variable never initialized before invoking the registry.","solutions":["Ensure a non-empty name is passed; validate before calling","Check where the name comes from (config, user input) and fix the empty source","Use Optional or a contains(name) check first to avoid null/empty calls"],"exampleFix":"// before\nregistry.readSkillContent(skillName);\n// after\nif (skillName != null && !skillName.isEmpty()) {\n    String content = registry.readSkillContent(skillName);\n}","handlingStrategy":"validation","validationCode":"if (name == null || name.isEmpty()) { throw new IllegalArgumentException(\"skill name required\"); }","typeGuard":"boolean isValidName(String s) { return s != null && !s.isEmpty(); }","tryCatchPattern":"try { content = registry.readSkillContent(name); } catch (IllegalArgumentException e) { log.warn(\"Invalid skill name\", e); }","preventionTips":["Validate names at the boundary where they enter your code","Avoid passing config-derived strings unchecked into registry APIs"],"tags":["java","validation","skills","argument-validation"],"backgroundTag":"missing-required-argument","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"}