{"record":{"id":"700dd36f962f98bf","repo":"alibaba/nacos","slug":"skill-name-cannot-be-blank","errorCode":null,"errorMessage":"Skill name cannot be blank","messagePattern":"Skill 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":115,"sourceCode":"    \n    /**\n     * Convert Skill object to a ZIP byte array containing all skill files.\n     *\n     * <p>The ZIP structure mirrors the upload format:\n     * {@code skillName/SKILL.md}, {@code skillName/type/resourceName}, etc.\n     * Binary resources (marked with metadata encoding=base64) are decoded back to raw bytes.</p>\n     *\n     * @param skill the Skill object to convert\n     * @return ZIP file as byte array\n     * @throws IOException if ZIP creation fails\n     * @throws IllegalArgumentException if skill is null or skill name is blank\n     */\n    public static byte[] toZipBytes(Skill skill) throws IOException {\n        if (skill == null) {\n            throw new IllegalArgumentException(\"Skill cannot be null\");\n        }\n        if (StringUtils.isBlank(skill.getName())) {\n            throw new IllegalArgumentException(\"Skill name cannot be blank\");\n        }\n        \n        String skillName = skill.getName();\n        ByteArrayOutputStream baos = new ByteArrayOutputStream();\n        try (ZipOutputStream zos = new ZipOutputStream(baos)) {\n            // 1. SKILL.md\n            zos.putNextEntry(new ZipEntry(skillName + \"/SKILL.md\"));\n            zos.write(toMarkdown(skill).getBytes(StandardCharsets.UTF_8));\n            zos.closeEntry();\n            \n            // 2. Resource files\n            if (skill.getResource() != null && !skill.getResource().isEmpty()) {\n                for (SkillResource resource : skill.getResource().values()) {\n                    if (resource == null || StringUtils.isBlank(resource.getName())) {\n                        continue;\n                    }\n                    String entryPath = buildZipEntryPath(skillName, resource);\n                    zos.putNextEntry(new ZipEntry(entryPath));","sourceCodeStart":97,"sourceCodeEnd":133,"githubUrl":"https://github.com/alibaba/nacos/blob/9b989acdf181d00898f2e8839257bb2b2a3cefe3/api/src/main/java/com/alibaba/nacos/api/ai/model/skills/SkillUtils.java#L97-L133","documentation":"SkillUtils.toZipBytes throws IllegalArgumentException when the Skill object is non-null but its getName() returns a blank value. The skill name is used as the root directory in the ZIP structure (skillName/SKILL.md), so it must be a valid non-blank identifier.","triggerScenarios":"Calling toZipBytes with a Skill whose name field is null, empty, or whitespace. Happens when a Skill object is partially constructed or deserialized from JSON that omits the name field.","commonSituations":"A Skill object built from a request body where the name field was absent. A deserialized Skill from a malformed config. A test fixture that forgot to set the name.","solutions":["Validate skill.getName() is non-blank before calling toZipBytes.","Enforce name presence at the Skill builder or constructor level.","Return a validation error to the API caller when name is missing."],"exampleFix":"// before\nSkill skill = new Skill();\nskill.setResource(resources);\n// name never set\nbyte[] zip = SkillUtils.toZipBytes(skill); // throws\n\n// after\nSkill skill = new Skill();\nskill.setName(\"my-skill\");\nskill.setResource(resources);\nbyte[] zip = SkillUtils.toZipBytes(skill); // ok","handlingStrategy":"validation","validationCode":"if (skill == null || StringUtils.isBlank(skill.getName())) {\n    throw new IllegalArgumentException(\"Skill name is required\");\n}\nbyte[] zip = SkillUtils.toZipBytes(skill);","typeGuard":"public static boolean hasValidSkillName(Skill skill) {\n    return skill != null && skill.getName() != null && !skill.getName().trim().isEmpty();\n}","tryCatchPattern":"try {\n    byte[] zip = SkillUtils.toZipBytes(skill);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().contains(\"Skill name cannot be blank\")) {\n        return badRequest(\"Skill name is required\");\n    }\n    throw e;\n}","preventionTips":["Enforce name presence at Skill construction or builder level.","Validate deserialized Skill objects before processing.","Reject skill uploads without a valid name at the API boundary."],"tags":["skill","validation","blank","zip"],"backgroundTag":null,"analyzedSha":"9b989acdf181d00898f2e8839257bb2b2a3cefe3","analyzedAt":"2026-08-14T07:17:31.569Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}