conductor-oss/conductor · error · IllegalArgumentException

Skill package exceeds max file count of {maxFileCount}

Error message

Skill package exceeds max file count of {maxFileCount}

What it means

Thrown by parseSkillPackage when the number of non-directory entries in the zip reaches maxFileCount (default 2000, configurable via agentspan.skills.max-file-count). The check fires at the top of the per-entry loop before reading each entry's content, so it stops early once the cap is hit.

Source

Thrown at agentspan/src/main/java/org/conductoross/conductor/ai/agentspan/runtime/service/SkillRegistryService.java:437

        } catch (IOException e) {
            throw new IllegalArgumentException(
                    "Failed to read skill package: " + e.getMessage(), e);
        }
    }

    @SuppressWarnings("unchecked")
    private ParsedSkillPackage parseSkillPackage(byte[] bytes, Map<String, Object> manifest) {
        List<SkillFileEntry> files = new ArrayList<>();
        Map<String, byte[]> contentByPath = new TreeMap<>();
        long totalUncompressedBytes = 0;
        try (ZipInputStream zip = new ZipInputStream(new ByteArrayInputStream(bytes))) {
            ZipEntry entry;
            while ((entry = zip.getNextEntry()) != null) {
                if (entry.isDirectory()) {
                    continue;
                }
                if (files.size() >= maxFileCount) {
                    throw new IllegalArgumentException(
                            "Skill package exceeds max file count of " + maxFileCount);
                }
                String path = normalizeEntryName(entry.getName());
                if (contentByPath.containsKey(path)) {
                    throw new IllegalArgumentException(
                            "Skill package contains duplicate path: " + path);
                }
                MessageDigest digest = MessageDigest.getInstance("SHA-256");
                long size = 0;
                ByteArrayOutputStream content = new ByteArrayOutputStream();
                byte[] buffer = new byte[8192];
                int read;
                while ((read = zip.read(buffer)) >= 0) {
                    digest.update(buffer, 0, read);
                    content.write(buffer, 0, read);
                    size += read;
                    totalUncompressedBytes += read;
                    if (size > maxPackageBytes) {

View on GitHub (pinned to cf7c3e4a8a)

Solutions

  1. Clean the package: exclude node_modules, target/, dist/, .git, and other generated trees before zipping.
  2. Raise agentspan.skills.max-file-count if a large file count is genuinely needed.
  3. Build the zip from an explicit allowlist of files rather than a recursive directory.

Example fix

# before
zip -r skill.zip .   # captures node_modules
# after (explicit allowlist)
zip skill.zip SKILL.md scripts/ references/
Defensive patterns

Strategy: validation

Validate before calling

// Before zipping, count the files you intend to include
long count;
try (var z = new ZipFile(packageFile)) { count = z.stream().filter(e -> !e.isDirectory()).count(); }
if (count > maxFileCount) { throw new IllegalArgumentException("too many files: " + count); }

Type guard

static boolean withinFileCount(long count, int maxFileCount) { return count <= maxFileCount; }

Try / catch

try { skillRegistryService.register(manifest, pkg); }
catch (IllegalArgumentException e) {
    if (e.getMessage().contains("exceeds max file count")) { /* prune vendored/generated files */ }
    else throw e;
}

Prevention

When it happens

Trigger: POST /api/skills/register with a zip containing more than 2000 files — e.g. a skill that accidentally bundled node_modules, a git repo, or a generated asset tree.

Common situations: Running 'zip -r skill.zip .' from the wrong directory and capturing vendored deps or build output; a build step emitting thousands of small files; lowering max-file-count in config.

Related errors


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