{"record":{"id":"e766929f1956a863","repo":"alibaba/nacos","slug":"parameter-validate-error-e76692","errorCode":"PARAMETER_VALIDATE_ERROR","errorMessage":"Skill zip file is empty","messagePattern":"Skill zip file is empty","errorType":"validation","errorClass":"NacosApiException","httpStatus":400,"severity":"warning","filePath":"ai/src/main/java/com/alibaba/nacos/ai/utils/SkillZipParser.java","lineNumber":208,"sourceCode":"                e.getMessage());\n            return null;\n        }\n    }\n    \n    /**\n     * Parse skill from zip file bytes. Zip size must not exceed the limit returned by\n     * {@link #resolveMaxUploadBytes()} (configurable via {@value #CONFIG_MAX_UPLOAD_SIZE_MB}).\n     * Text files are decoded as UTF-8; binary files (by extension) are stored as Base64 with metadata encoding=base64.\n     *\n     * @param zipBytes zip file bytes\n     * @param namespaceId namespace ID\n     * @return parsed skill\n     * @throws NacosApiException if parsing failed or zip exceeds size limit\n     */\n    public static Skill parseSkillFromZip(byte[] zipBytes, String namespaceId)\n        throws NacosApiException {\n        if (zipBytes == null || zipBytes.length == 0) {\n            throw new NacosApiException(NacosApiException.INVALID_PARAM,\n                ErrorCode.PARAMETER_VALIDATE_ERROR,\n                \"Skill zip file is empty\");\n        }\n        long maxUploadBytes = resolveMaxUploadBytes();\n        if (zipBytes.length > maxUploadBytes) {\n            throw new NacosApiException(NacosApiException.INVALID_PARAM,\n                ErrorCode.PARAMETER_VALIDATE_ERROR,\n                \"Skill zip size must not exceed \"\n                    + (maxUploadBytes / 1024 / 1024) + \"MB, current: \"\n                    + (zipBytes.length / 1024 / 1024) + \"MB\");\n        }\n        try {\n            List<ZipEntryData> entries = unzipToEntries(zipBytes);\n            ZipEntryData skillMdEntry = findSkillMdEntry(entries);\n            if (skillMdEntry == null) {\n                throw new NacosApiException(NacosApiException.INVALID_PARAM,\n                    ErrorCode.PARAMETER_VALIDATE_ERROR,\n                    \"SKILL.md file not found in zip\");","sourceCodeStart":190,"sourceCodeEnd":226,"githubUrl":"https://github.com/alibaba/nacos/blob/9b989acdf181d00898f2e8839257bb2b2a3cefe3/ai/src/main/java/com/alibaba/nacos/ai/utils/SkillZipParser.java#L190-L226","documentation":"Thrown by SkillZipParser.parseSkillFromZip when the provided zipBytes array is null or has zero length. This is the first validation check before attempting to unzip. It fires when the caller passes an empty byte array where a ZIP archive is expected.","triggerScenarios":"Calling parseSkillFromZip programmatically with a null or empty byte array. In the HTTP path, this is unlikely because validateAndExtractZipBytes (error 389) catches empty files first, but direct service-layer or test code can reach this method with empty bytes.","commonSituations":"A test calls parseSkillFromZip with an empty byte array; a service-layer method passes through a null after failed upstream processing; a ZIP download from a remote source returned an empty response body; a file read returned 0 bytes but the null/empty check upstream was bypassed.","solutions":["Verify the zipBytes array is non-null and has length > 0 before calling parseSkillFromZip.","If reading bytes from a file or stream, check the byte array length after reading and before passing to the parser.","Add a guard in calling code: if (zipBytes == null || zipBytes.length == 0) throw early with a descriptive error.","Trace upstream to find where the empty bytes originated — a failed download, a truncated read, or a logic error."],"exampleFix":"// before — no guard before calling parser\nSkill skill = SkillZipParser.parseSkillFromZip(bytes, namespaceId);\n\n// after — validate non-empty first\nif (bytes == null || bytes.length == 0) {\n    throw new IllegalArgumentException(\"Skill ZIP bytes must not be null or empty\");\n}\nSkill skill = SkillZipParser.parseSkillFromZip(bytes, namespaceId);","handlingStrategy":"validation","validationCode":"// Check zipBytes before calling parseSkillFromZip\nif (zipBytes == null || zipBytes.length == 0) {\n    throw new IllegalArgumentException(\"Skill ZIP bytes must not be null or empty\");\n}","typeGuard":"public static boolean isNonEmptyZipBytes(byte[] zipBytes) {\n    return zipBytes != null && zipBytes.length > 0;\n}","tryCatchPattern":"try {\n    Skill skill = SkillZipParser.parseSkillFromZip(zipBytes, namespaceId);\n} catch (NacosApiException e) {\n    if (ErrorCode.PARAMETER_VALIDATE_ERROR.equals(e.getErrDetail())\n        && e.getErrMsg().contains(\"empty\")) {\n        return \"The provided ZIP file is empty. Please provide a valid skill archive.\";\n    }\n    throw e;\n}","preventionTips":["Always validate byte array length before passing to the parser.","For file-based imports, verify file.exists() && file.length() > 0 before reading.","Add a null-check guard in service-layer code that calls parseSkillFromZip directly."],"tags":["skill","zip-parsing","parameter-validation","empty-input"],"backgroundTag":null,"analyzedSha":"9b989acdf181d00898f2e8839257bb2b2a3cefe3","analyzedAt":"2026-08-14T07:17:31.569Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}