conductor-oss/conductor · error · IllegalArgumentException

Skill file not found: {cleanPath}

Error message

Skill file not found: {cleanPath}

What it means

Thrown by readFile() when the requested cleanPath does not match any non-directory entry inside the skill's zip package. The lookup normalizes both the requested path and each entry name (strips leading ./, converts backslashes) and compares for exact equality. A wrong path, a path with a different folder prefix, or a path to a directory yields this.

Source

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

                    throw new IllegalArgumentException(
                            "Skill file is too large to preview: " + cleanPath);
                }
                byte[] data =
                        readBounded(
                                zip,
                                maxPreviewBytes,
                                "Skill file is too large to preview: " + cleanPath);
                boolean binary = isBinary(cleanPath, data);
                return SkillFileContent.builder()
                        .path(cleanPath)
                        .contentType(contentType(cleanPath))
                        .size(data.length)
                        .binary(binary)
                        .content(binary ? null : new String(data, StandardCharsets.UTF_8))
                        .contentBase64(binary ? Base64.getEncoder().encodeToString(data) : null)
                        .build();
            }
            throw new IllegalArgumentException("Skill file not found: " + cleanPath);
        } catch (IOException e) {
            throw new IllegalStateException("Failed to read skill file: " + e.getMessage(), e);
        }
    }

    @SuppressWarnings("unchecked")
    public Map<String, Object> resolveRawConfig(Map<String, Object> skillRef) {
        requireSkillStorage();
        if (skillRef == null) {
            throw new IllegalArgumentException("skillRef is required");
        }
        String name = requiredString(skillRef, "name");
        String version = stringValue(skillRef.get("version"));
        SkillDetail detail = get(name, version);
        Map<String, Object> rawConfig = rawConfigForDetail(detail, new HashSet<>());
        Object model = skillRef.get("model");
        if (model instanceof String s && !s.isBlank()) {
            rawConfig.put("model", s);

View on GitHub (pinned to cf7c3e4a8a)

Solutions

  1. First GET /api/skills/{name}/versions/{version} and read the files[] array for the exact normalized path.
  2. Make sure the path matches an entry name verbatim, including any subfolder prefix like scripts/ or references/.
  3. Request a file, not a directory — directory entries are intentionally skipped.

Example fix

// before (wrong path)
GET /api/skills/foo/versions/1.0.0/files?path=README.md
// after (path from files[] list)
GET /api/skills/foo/versions/1.0.0/files?path=docs/README.md
Defensive patterns

Strategy: validation

Validate before calling

// Validate path exists in the skill's file list before reading
SkillDetail d = skillRegistryService.get(name, version);
Set<String> valid = d.getFiles().stream().map(SkillFileEntry::getPath).collect(Collectors.toSet());
if (!valid.contains(path)) { throw new NoSuchElementException("unknown path " + path); }
skillRegistryService.readFile(name, version, path);

Type guard

static boolean pathExistsInSkill(String path, SkillDetail d) {
    return d.getFiles().stream().anyMatch(f -> f.getPath().equals(path));
}

Try / catch

try { return skillRegistryService.readFile(name, version, path); }
catch (IllegalArgumentException e) {
    if (e.getMessage().startsWith("Skill file not found")) { /* refresh skill detail, pick a valid path */ }
    else throw e;
}

Prevention

When it happens

Trigger: GET /api/skills/foo/versions/1.0.0/files?path=README.md when the actual entry is docs/README.md, or path=scripts/ when only files exist (directories are skipped). Also when the path has a typo or stale name from an older package version.

Common situations: Guessing a path instead of reading the skill detail's files list; package layout changed across versions but client hardcodes an old path; requesting a folder path rather than a file.

Related errors


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