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
- Clean the package: exclude node_modules, target/, dist/, .git, and other generated trees before zipping.
- Raise agentspan.skills.max-file-count if a large file count is genuinely needed.
- 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
- Build the zip from an explicit allowlist, never a bare recursive directory.
- Add a .gitignore-style exclusion for node_modules, target, dist in the packaging script.
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
- Skill package contains oversized file: {path}
- Skill package exceeds max size of {maxPackageBytes} bytes
- Skill package contains duplicate path: {path}
- Skill package exceeds max uncompressed size of {maxUncompres
- Invalid skill package zip: {e.getMessage()}
AI-assisted analysis of conductor-oss/conductor@cf7c3e4a8a (2026-08-14).
Data as JSON: /api/errors/9a23da127d2ac31d.
Report an issue: GitHub.