{"record":{"id":"ede590684ba35ebf","repo":"alibaba/nacos","slug":"skill-directory-name-cannot-be-blank","errorCode":null,"errorMessage":"Skill directory name cannot be blank","messagePattern":"Skill directory name cannot be blank","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"api/src/main/java/com/alibaba/nacos/api/ai/model/skills/SkillUtils.java","lineNumber":362,"sourceCode":"     */\n    public static void syncToLocal(Skill skill, String baseDir, String skillDirName,\n        ExistingDirectoryStrategy strategy) throws IOException {\n        if (skill == null) {\n            throw new IllegalArgumentException(\"Skill cannot be null\");\n        }\n        \n        if (StringUtils.isBlank(baseDir)) {\n            throw new IllegalArgumentException(\"Base directory cannot be blank\");\n        }\n        \n        if (strategy == null) {\n            strategy = ExistingDirectoryStrategy.OVERWRITE;\n        }\n        \n        // Use custom directory name or fall back to skill name\n        String dirName = !StringUtils.isBlank(skillDirName) ? skillDirName : skill.getName();\n        if (StringUtils.isBlank(dirName)) {\n            throw new IllegalArgumentException(\"Skill directory name cannot be blank\");\n        }\n        \n        // Create skill directory path: {baseDir}/{skillDirName}\n        Path basePath = Paths.get(baseDir);\n        Path skillDir = basePath.resolve(dirName);\n        \n        // Delegate to core implementation\n        syncToLocalCore(skill, skillDir, basePath, strategy);\n    }\n    \n    /**\n     * Core implementation for syncing Skill to local directory.\n     * This method contains the common logic for all syncToLocal variants.\n     *\n     * @param skill the Skill object to sync\n     * @param skillDir the target skill directory path\n     * @param basePath the base directory path\n     * @param strategy the strategy for handling existing directories","sourceCodeStart":344,"sourceCodeEnd":380,"githubUrl":"https://github.com/alibaba/nacos/blob/9b989acdf181d00898f2e8839257bb2b2a3cefe3/api/src/main/java/com/alibaba/nacos/api/ai/model/skills/SkillUtils.java#L344-L380","documentation":"Thrown by the four-argument SkillUtils.syncToLocal as an IllegalArgumentException when the resolved directory name is blank. The directory name is skillDirName if non-blank, otherwise skill.getName(); this error means BOTH were blank/null, so no directory name could be derived.","triggerScenarios":"Calling syncToLocal(skill, baseDir, skillDirName, strategy) where skillDirName is null/blank AND skill.getName() is also null/blank. The skill object exists but has no name, and no explicit directory name was supplied.","commonSituations":"A Skill was deserialized with a missing name field and the caller did not pass a skillDirName; a custom directory name argument was computed from another empty field.","solutions":["Pass an explicit, non-blank skillDirName when the Skill's own name may be absent.","Ensure the Skill has a non-blank name (it is required for the resource identity).","Validate both skill.getName() and skillDirName before calling and reject the entry if both are blank."],"exampleFix":"// before\nSkill skill = new Skill(); // name not set\nSkillUtils.syncToLocal(skill, baseDir, null, OVERWRITE); // throws\n\n// after\nSkill skill = new Skill();\nskill.setName(\"my-skill\");\nSkillUtils.syncToLocal(skill, baseDir, null, OVERWRITE); // uses name, ok\n// or pass explicit dir name:\nSkillUtils.syncToLocal(skill, baseDir, \"my-skill-dir\", OVERWRITE); // ok","handlingStrategy":"validation","validationCode":"String dirName = !StringUtils.isBlank(skillDirName) ? skillDirName : skill.getName();\nif (StringUtils.isBlank(dirName)) {\n    throw new IllegalStateException(\"No directory name available (skillDirName blank and skill has no name)\");\n}\nSkillUtils.syncToLocal(skill, baseDir, skillDirName, strategy);","typeGuard":"static boolean hasUsableDirName(String skillDirName, Skill skill) {\n    return !StringUtils.isBlank(skillDirName)\n        || (skill != null && !StringUtils.isBlank(skill.getName()));\n}","tryCatchPattern":null,"preventionTips":["Always pass an explicit skillDirName when the Skill's name might be absent.","Ensure the Skill has a name before it reaches the sync layer.","When deriving dirName from multiple sources, compute and validate it once upstream."],"tags":["java","nacos","ai","skills","validation"],"backgroundTag":null,"analyzedSha":"9b989acdf181d00898f2e8839257bb2b2a3cefe3","analyzedAt":"2026-08-14T07:17:31.569Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}