alibaba/nacos · error · NacosApiException

PARSING_DATA_FAILED

PARSING_DATA_FAILED

Error message

Failed to parse zip file: " + e.getMessage()

What it means

Thrown by SkillZipParser.parseSkillFromZip as the catch-all for any non-NacosApiException exception during ZIP parsing. This covers failures in unzipToEntries (ZipArchiveInputStream errors, security-limit violations via NacosRuntimeException), parseSkillMarkdown (invalid YAML, missing frontmatter), and parseResources. The original exception is logged and its message is included in the error.

Solutions

  1. Check server logs for the full stack trace — the chained exception (e) identifies the exact cause.
  2. If the ZIP is corrupted, re-download or re-create it from the source.
  3. If the error is a security-limit violation (too many entries, uncompressed size exceeded), raise nacos.ai.skill.zip.max-entries or nacos.ai.skill.zip.max-uncompressed-size-mb if the skill legitimately needs more.
  4. If the error is a path-traversal rejection, inspect the ZIP for entries containing '..' or absolute paths and remove them.
  5. If the error is YAML-related, validate the SKILL.md frontmatter syntax with a YAML linter before zipping.

Example fix

// before — ZIP contains a path-traversal entry
// entry: ../../../etc/passwd

// after — re-create ZIP without malicious entries
// zip -r skill.zip SKILL.md resources/  (from inside the skill directory)
// verify: unzip -l skill.zip  (no entries with '..')
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-validate ZIP structure before calling parseSkillFromZip
if (zipBytes == null || zipBytes.length == 0) {
    throw new IllegalArgumentException("ZIP is empty");
}
// Check ZIP magic bytes
if (zipBytes.length < 4 || (zipBytes[0] != 0x50 || zipBytes[1] != 0x4B)) {
    throw new IllegalArgumentException("Not a valid ZIP file (missing PK magic bytes)");
}

Type guard

public static boolean isValidZipArchive(byte[] zipBytes) {
    return zipBytes != null && zipBytes.length >= 4
        && zipBytes[0] == 0x50 && zipBytes[1] == 0x4B // PK magic
        && zipBytes.length <= SkillZipParser.resolveMaxUploadBytes();
}

Try / catch

try {
    Skill skill = SkillZipParser.parseSkillFromZip(zipBytes, namespaceId);
} catch (NacosApiException e) {
    if (ErrorCode.PARSING_DATA_FAILED.equals(e.getErrDetail())) {
        log.error("Failed to parse skill ZIP: {}", e.getErrMsg(), e);
        return ResponseEntity.badRequest()
            .body("Could not parse the ZIP file. Check the archive integrity and SKILL.md format. Detail: "
                + e.getErrMsg());
    }
    throw e;
}

Prevention

When it happens

Trigger: Uploading a ZIP that triggers any unexpected exception during parsing: a corrupted ZIP archive that Apache Commons Compress cannot read; a path-traversal entry ('../') caught by SkillUtils.validatePathSafety; a ZIP bomb exceeding the uncompressed size limit; a SKILL.md with malformed YAML frontmatter; a resource entry with an invalid name pattern.

Common situations: Corrupted or truncated ZIP file from a failed download; a ZIP created by a tool that produces entries Apache Commons Compress cannot handle; a malicious or accidental path-traversal entry in the ZIP; exceeding the max-entries or max-uncompressed-size limits; SKILL.md YAML frontmatter that is syntactically broken (e.g. missing colon, unbalanced quotes).

Understand the failure class

Related errors


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

Appendix: source

Thrown at ai/src/main/java/com/alibaba/nacos/ai/utils/SkillZipParser.java:248

            if (StringUtils.isBlank(skillMdContent)) {
                throw new NacosApiException(NacosApiException.INVALID_PARAM,
                    ErrorCode.PARAMETER_VALIDATE_ERROR,
                    "SKILL.md file not found in zip");
            }
            
            Skill skill = parseSkillMarkdown(skillMdContent, namespaceId);
            List<ZipEntryData> resourceEntries =
                filterEntriesByPrefix(entries, getSkillPrefix(skillMdEntry.name));
            Map<String, SkillResource> resources =
                parseResources(resourceEntries, skill.getName(), SKILL_MD_FILE);
            skill.setResource(resources);
            
            return skill;
        } catch (NacosApiException e) {
            throw e;
        } catch (Exception e) {
            LOGGER.error("Failed to parse skill zip file", e);
            throw new NacosApiException(NacosApiException.INVALID_PARAM,
                ErrorCode.PARSING_DATA_FAILED,
                "Failed to parse zip file: " + e.getMessage());
        }
    }
    
    /**
     * Parse multiple skills from a single zip archive. Supports zip files containing multiple skill subdirectories,
     * each with its own SKILL.md. If only one SKILL.md is found, returns a list with a single element.
     *
     * <p>Expected zip structure for multi-skill:
     * <pre>
     * skills.zip
     * ├── skill-a/
     * │   ├── SKILL.md
     * │   └── resource.txt
     * ├── skill-b/
     * │   ├── SKILL.md
     * │   └── template/prompt.md

View on GitHub (pinned to 9b989acdf1)