alibaba/nacos · error · IllegalArgumentException

Invalid ZIP data: missing ZIP magic header (PK\x03\x04)

Error message

Invalid ZIP data: missing ZIP magic header (PK\x03\x04)

What it means

Thrown by SkillUtils.validateZipBytes as an IllegalArgumentException when the byte array is at least 30 bytes long but its first four bytes are not the ZIP local-file-header signature 0x50 0x4B 0x03 0x04 ('PK\x03\x04'). This detects data that is the wrong format (e.g. a gzip, tar, or text body) masquerading as a ZIP.

Source

Thrown at api/src/main/java/com/alibaba/nacos/api/ai/model/skills/SkillUtils.java:207

            throw new SecurityException(
                "Path escapes target directory: " + target + " is outside " + baseDir);
        }
    }
    
    /**
     * Validate that byte array is a valid ZIP file by checking the magic number header.
     *
     * @param data the byte array to validate
     * @throws IllegalArgumentException if data is null, too short, or does not have ZIP magic header
     */
    public static void validateZipBytes(byte[] data) {
        if (data == null || data.length < ZIP_MIN_SIZE) {
            throw new IllegalArgumentException(
                "Invalid ZIP data: too short (" + (data == null ? 0 : data.length) + " bytes)");
        }
        for (int i = 0; i < ZIP_MAGIC.length; i++) {
            if (data[i] != ZIP_MAGIC[i]) {
                throw new IllegalArgumentException(
                    "Invalid ZIP data: missing ZIP magic header (PK\\x03\\x04)");
            }
        }
    }
    
    /**
     * Validate all ZIP entry paths for path traversal and absolute paths.
     *
     * <p>Scans entry names only without decompressing content, so it is lightweight
     * and suitable for validating downloaded ZIP bytes on the client side.</p>
     *
     * @param data the ZIP byte array to validate
     * @throws SecurityException if any entry contains path traversal or absolute path
     * @throws IOException if ZIP cannot be read
     */
    public static void validateZipEntryPaths(byte[] data) throws IOException {
        try (ZipInputStream zis = new ZipInputStream(new ByteArrayInputStream(data))) {
            ZipEntry entry;

View on GitHub (pinned to 9b989acdf1)

Solutions

  1. Confirm the producer actually created a standard ZIP (PK\x03\x04) and not gzip/tar.
  2. Inspect the first bytes of the array (HexFormat.of().formatHex) to identify the real format.
  3. Re-export the skill as a ZIP and re-upload to the server.

Example fix

// before
byte[] data = "{\"error\":\"not found\"}".getBytes();
SkillUtils.validateZipBytes(data); // throws: missing magic

// after
byte[] data = SkillUtils.toZipBytes(skill); // produces valid PK ZIP
SkillUtils.validateZipBytes(data); // ok
Defensive patterns

Strategy: validation

Validate before calling

static boolean hasZipMagic(byte[] data) {
    return data != null && data.length >= 4
        && (data[0] & 0xFF) == 0x50 && (data[1] & 0xFF) == 0x4B
        && (data[2] & 0xFF) == 0x03 && (data[3] & 0xFF) == 0x04;
}
if (!hasZipMagic(data)) {
    throw new IOException("Expected ZIP (PK), got " + describeMagic(data));
}
SkillUtils.validateZipBytes(data);

Type guard

static boolean isZipFormat(byte[] data) {
    return data != null && data.length >= 4
        && data[0] == 0x50 && data[1] == 0x4B
        && data[2] == 0x03 && data[3] == 0x04;
}

Try / catch

try {
    SkillUtils.validateZipBytes(data);
} catch (IllegalArgumentException e) {
    log.error("Not a ZIP. First bytes: {}", HexFormat.of().formatHex(Arrays.copyOf(data, 8)));
    throw e;
}

Prevention

When it happens

Trigger: Calling validateZipBytes on a byte array whose magic number differs — e.g. a gzip stream (0x1f 0x8b), a plain JSON/text body, or a tar archive. Often happens when the skill content field held non-ZIP data or the server returned an error page instead of a ZIP.

Common situations: The skill 'content' was a raw markdown string rather than a ZIP; a CDN/proxy returned an HTML error page (200 with text) that was buffered as bytes; the producer used tar.gz instead of zip.

Related errors


AI-assisted analysis of alibaba/nacos@9b989acdf1 (2026-08-14). Data as JSON: /api/errors/18ce8f7e9c67dbb1. Report an issue: GitHub.