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

  1. Verify the uploaded file is a valid zip locally: unzip -t skill.zip.
  2. Re-export the zip from source and re-upload.
  3. 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

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


AI-assisted analysis of conductor-oss/conductor@cf7c3e4a8a (2026-08-14). Data as JSON: /api/errors/54b17dbc282d6a21. Report an issue: GitHub.