{"record":{"id":"3deb0605bd484adb","repo":"conductor-oss/conductor","slug":"skill-file-not-found-cleanpath","errorCode":null,"errorMessage":"Skill file not found: {cleanPath}","messagePattern":"Skill file not found: (.+?)","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"agentspan/src/main/java/org/conductoross/conductor/ai/agentspan/runtime/service/SkillRegistryService.java","lineNumber":297,"sourceCode":"                    throw new IllegalArgumentException(\n                            \"Skill file is too large to preview: \" + cleanPath);\n                }\n                byte[] data =\n                        readBounded(\n                                zip,\n                                maxPreviewBytes,\n                                \"Skill file is too large to preview: \" + cleanPath);\n                boolean binary = isBinary(cleanPath, data);\n                return SkillFileContent.builder()\n                        .path(cleanPath)\n                        .contentType(contentType(cleanPath))\n                        .size(data.length)\n                        .binary(binary)\n                        .content(binary ? null : new String(data, StandardCharsets.UTF_8))\n                        .contentBase64(binary ? Base64.getEncoder().encodeToString(data) : null)\n                        .build();\n            }\n            throw new IllegalArgumentException(\"Skill file not found: \" + cleanPath);\n        } catch (IOException e) {\n            throw new IllegalStateException(\"Failed to read skill file: \" + e.getMessage(), e);\n        }\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    public Map<String, Object> resolveRawConfig(Map<String, Object> skillRef) {\n        requireSkillStorage();\n        if (skillRef == null) {\n            throw new IllegalArgumentException(\"skillRef is required\");\n        }\n        String name = requiredString(skillRef, \"name\");\n        String version = stringValue(skillRef.get(\"version\"));\n        SkillDetail detail = get(name, version);\n        Map<String, Object> rawConfig = rawConfigForDetail(detail, new HashSet<>());\n        Object model = skillRef.get(\"model\");\n        if (model instanceof String s && !s.isBlank()) {\n            rawConfig.put(\"model\", s);","sourceCodeStart":279,"sourceCodeEnd":315,"githubUrl":"https://github.com/conductor-oss/conductor/blob/cf7c3e4a8adfb158be778ab1ec525323c363cd3a/agentspan/src/main/java/org/conductoross/conductor/ai/agentspan/runtime/service/SkillRegistryService.java#L279-L315","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["First GET /api/skills/{name}/versions/{version} and read the files[] array for the exact normalized path.","Make sure the path matches an entry name verbatim, including any subfolder prefix like scripts/ or references/.","Request a file, not a directory — directory entries are intentionally skipped."],"exampleFix":"// before (wrong path)\nGET /api/skills/foo/versions/1.0.0/files?path=README.md\n// after (path from files[] list)\nGET /api/skills/foo/versions/1.0.0/files?path=docs/README.md","handlingStrategy":"validation","validationCode":"// Validate path exists in the skill's file list before reading\nSkillDetail d = skillRegistryService.get(name, version);\nSet<String> valid = d.getFiles().stream().map(SkillFileEntry::getPath).collect(Collectors.toSet());\nif (!valid.contains(path)) { throw new NoSuchElementException(\"unknown path \" + path); }\nskillRegistryService.readFile(name, version, path);","typeGuard":"static boolean pathExistsInSkill(String path, SkillDetail d) {\n    return d.getFiles().stream().anyMatch(f -> f.getPath().equals(path));\n}","tryCatchPattern":"try { return skillRegistryService.readFile(name, version, path); }\ncatch (IllegalArgumentException e) {\n    if (e.getMessage().startsWith(\"Skill file not found\")) { /* refresh skill detail, pick a valid path */ }\n    else throw e;\n}","preventionTips":["Drive file-path selection from the skill detail's files[] list, never from guesses.","When the package version changes, re-fetch the file list before previewing."],"tags":["java","conductor","skill-registry","not-found","rest-api"],"backgroundTag":null,"analyzedSha":"cf7c3e4a8adfb158be778ab1ec525323c363cd3a","analyzedAt":"2026-08-14T03:33:19.897Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}