{"record":{"id":"917f47fcc419fa3b","repo":"alibaba/nacos","slug":"invalid-zip-data-too-short-length-bytes","errorCode":null,"errorMessage":"Invalid ZIP data: too short ({length} bytes)","messagePattern":"Invalid ZIP data: too short \\((.+?) bytes\\)","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"api/src/main/java/com/alibaba/nacos/api/ai/model/skills/SkillUtils.java","lineNumber":202,"sourceCode":"     * @param target  the resolved target path\n     * @throws SecurityException if target escapes baseDir\n     */\n    public static void validatePathContainment(Path baseDir, Path target) {\n        if (!target.normalize().startsWith(baseDir.normalize())) {\n            throw new SecurityException(\n                \"Path escapes target directory: \" + target + \" is outside \" + baseDir);\n        }\n    }\n    \n    /**\n     * Validate that byte array is a valid ZIP file by checking the magic number header.\n     *\n     * @param data the byte array to validate\n     * @throws IllegalArgumentException if data is null, too short, or does not have ZIP magic header\n     */\n    public static void validateZipBytes(byte[] data) {\n        if (data == null || data.length < ZIP_MIN_SIZE) {\n            throw new IllegalArgumentException(\n                \"Invalid ZIP data: too short (\" + (data == null ? 0 : data.length) + \" bytes)\");\n        }\n        for (int i = 0; i < ZIP_MAGIC.length; i++) {\n            if (data[i] != ZIP_MAGIC[i]) {\n                throw new IllegalArgumentException(\n                    \"Invalid ZIP data: missing ZIP magic header (PK\\\\x03\\\\x04)\");\n            }\n        }\n    }\n    \n    /**\n     * Validate all ZIP entry paths for path traversal and absolute paths.\n     *\n     * <p>Scans entry names only without decompressing content, so it is lightweight\n     * and suitable for validating downloaded ZIP bytes on the client side.</p>\n     *\n     * @param data the ZIP byte array to validate\n     * @throws SecurityException if any entry contains path traversal or absolute path","sourceCodeStart":184,"sourceCodeEnd":220,"githubUrl":"https://github.com/alibaba/nacos/blob/9b989acdf181d00898f2e8839257bb2b2a3cefe3/api/src/main/java/com/alibaba/nacos/api/ai/model/skills/SkillUtils.java#L184-L220","documentation":"Thrown by SkillUtils.validateZipBytes as an IllegalArgumentException when the byte array is null or shorter than 30 bytes (ZIP_MIN_SIZE, the length of a ZIP local file header). It is a pre-check before reading any magic bytes, protecting the caller from ArrayIndexOutOfBoundsException and detecting truncated or empty downloads.","triggerScenarios":"Calling SkillUtils.validateZipBytes(data) where data == null or data.length < 30. Common when a skill download returned an empty/short body or a corrupted/truncated byte array was passed from toZipBytes.","commonSituations":"Network download of a skill bundle was interrupted, leaving a partial body; a base64 decode of an empty content field produced a zero-length array; a resource was misconfigured and the ZIP payload is missing entirely.","solutions":["Verify the download completed and the Content-Length matches before calling validateZipBytes.","Check for null or data.length >= 30 before invoking, and surface a clearer download error to the user.","Re-fetch the skill bundle from the Nacos server and retry the sync."],"exampleFix":"// before\nbyte[] data = downloadSkillZip(id); // returned truncated 10 bytes\nSkillUtils.validateZipBytes(data); // throws\n\n// after\nbyte[] data = downloadSkillZip(id);\nif (data == null || data.length < 30) {\n    throw new IOException(\"Skill bundle download is empty or truncated\");\n}\nSkillUtils.validateZipBytes(data); // ok","handlingStrategy":"validation","validationCode":"static boolean isPlausibleZip(byte[] data) {\n    return data != null && data.length >= 30;\n}\nif (!isPlausibleZip(data)) {\n    throw new IOException(\"Skill bundle is empty or truncated (\" + (data == null ? 0 : data.length) + \" bytes)\");\n}\nSkillUtils.validateZipBytes(data);","typeGuard":"static boolean hasZipMinSize(byte[] data) {\n    return data != null && data.length >= 30;\n}","tryCatchPattern":"try {\n    SkillUtils.validateZipBytes(data);\n} catch (IllegalArgumentException e) {\n    // re-fetch the bundle or report download failure\n    throw new IOException(\"Invalid skill bundle, please re-download\", e);\n}","preventionTips":["Verify download Content-Length and byte count match before validating.","Treat < 30 bytes as a download/decode failure, not a ZIP format error.","Decode base64 content into a byte[] and length-check before passing to validateZipBytes."],"tags":["java","nacos","ai","skills","zip","validation"],"backgroundTag":null,"analyzedSha":"9b989acdf181d00898f2e8839257bb2b2a3cefe3","analyzedAt":"2026-08-14T07:17:31.569Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}