conductor-oss/conductor · error · IllegalArgumentException
Invalid skill package zip: {e.getMessage()}
Error message
Invalid skill package zip: {e.getMessage()} What it means
Thrown by parseSkillPackage as a catch-all IllegalArgumentException for any non-IllegalArgumentException Exception raised during zip streaming — most commonly java.util.zip.ZipException when the package is not a valid zip or is truncated. The original exception is attached as the cause. IllegalArgumentExceptions thrown inside the loop are re-thrown unchanged (the catch (IllegalArgumentException e) rethrows them).
Source
Thrown at agentspan/src/main/java/org/conductoross/conductor/ai/agentspan/runtime/service/SkillRegistryService.java:478
throw new IllegalArgumentException(
"Skill package exceeds max uncompressed size of "
+ maxUncompressedBytes
+ " bytes");
}
}
contentByPath.put(path, content.toByteArray());
files.add(
SkillFileEntry.builder()
.path(path)
.size(size)
.sha256(hex(digest.digest()))
.contentType(contentType(path))
.build());
}
} catch (IllegalArgumentException e) {
throw e;
} catch (Exception e) {
throw new IllegalArgumentException("Invalid skill package zip: " + e.getMessage(), e);
}
byte[] skillMdBytes = contentByPath.get("SKILL.md");
if (skillMdBytes == null) {
throw new IllegalArgumentException("Skill package is missing SKILL.md");
}
files.sort(Comparator.comparing(SkillFileEntry::getPath));
String skillMd = decodeUtf8("SKILL.md", skillMdBytes);
Map<String, Object> frontmatter = parseSkillFrontmatter(skillMd);
String name = requiredString(frontmatter, "name");
validateSkillName(name);
String description = stringValue(frontmatter.get("description"));
if (description == null || description.isBlank()) {
description = stringValue(manifest.get("description"));
}
Map<String, String> agentFiles = new LinkedHashMap<>();View on GitHub (pinned to cf7c3e4a8a)
Solutions
- Verify the uploaded file is a valid zip locally: unzip -t skill.zip.
- Re-export the zip from source and re-upload.
- Inspect the caused-by exception (ZipException message) for the structural failure point.
Example fix
# before: uploading a .tar.gz as the package curl -F 'package=@skill.tar.gz' ... # after: upload a real zip curl -F 'package=@skill.zip' ...
Defensive patterns
Strategy: validation
Validate before calling
// Before uploading, verify the package is a structurally valid zip
try (var z = new ZipFile(packageFile)) { z.stream().count(); } // throws ZipException if invalid
Type guard
static boolean isValidZip(java.io.File f) {
try (var z = new ZipFile(f)) { z.stream().count(); return true; }
catch (java.io.IOException e) { return false; }
} Try / catch
try { skillRegistryService.register(manifest, pkg); }
catch (IllegalArgumentException e) {
if (e.getMessage().startsWith("Invalid skill package zip")) { /* re-export a valid zip, retry */ }
else throw e;
} Prevention
- Validate the zip with unzip -t or a ZipFile open before uploading.
- Ensure the build step writes a properly closed, non-truncated zip.
When it happens
Trigger: POST /api/skills/register where the 'package' part is not a zip at all (e.g. a tar, a raw file, an HTML error page), or a zip that is truncated/corrupt so ZipInputStream.getNextEntry() fails.
Common situations: Client uploading the wrong file type; a download/CI step that produced a partial zip; double-compression or a content-encoding mismatch corrupting the bytes; an upstream proxy rewriting the body.
Related errors
- Skill package contains duplicate path: {path}
- Skill package is missing SKILL.md
- Skill package exceeds max file count of {maxFileCount}
- Skill package contains oversized file: {path}
- Skill package contains duplicate script tool name: {toolName
AI-assisted analysis of conductor-oss/conductor@cf7c3e4a8a (2026-08-14).
Data as JSON: /api/errors/54b17dbc282d6a21.
Report an issue: GitHub.