{"record":{"id":"374e327e9b11ed59","repo":"alibaba/spring-ai-alibaba","slug":"cannot-convert-resource-to-file-system-path-374e32","errorCode":null,"errorMessage":"Cannot convert resource to file system path: {}","messagePattern":"Cannot convert resource to file system path: (.+?)","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"spring-ai-alibaba-graph-core/src/main/java/com/alibaba/cloud/ai/graph/skills/SpringAiSkillAdvisor.java","lineNumber":320,"sourceCode":"\n\t\t/**\n\t\t * Set the user skills directory from a Spring Resource.\n\t\t * <p><b>Optional</b>: Defaults to <code>~/saa/skills</code> if not specified.\n\t\t * <p>The Resource will be converted to a file system path. If the resource cannot be\n\t\t * resolved to a file (e.g., it's inside a JAR), an IllegalArgumentException will be thrown.\n\t\t *\n\t\t * @param resource the Resource pointing to the user-level skills directory\n\t\t * @return this builder\n\t\t * @throws IllegalArgumentException if the resource cannot be converted to a file system path\n\t\t */\n\t\tpublic Builder userSkillsDirectory(Resource resource) {\n\t\t\ttry {\n\t\t\t\tif (resource != null && resource.exists()) {\n\t\t\t\t\tFile file = resource.getFile();\n\t\t\t\t\tthis.userSkillsDirectory = file.getAbsolutePath();\n\t\t\t\t}\n\t\t\t} catch (IOException e) {\n\t\t\t\tthrow new IllegalArgumentException(\"Cannot convert resource to file system path: \" + resource, e);\n\t\t\t}\n\t\t\treturn this;\n\t\t}\n\n\t\t/**\n\t\t * Set the project skills directory.\n\t\t * <p><b>Optional</b>: Defaults to <code>classpath:skills</code> or <code>./skills</code> if not specified.\n\t\t *\n\t\t * @param projectSkillsDirectory the project skills directory path\n\t\t * @return this builder\n\t\t */\n\t\tpublic Builder projectSkillsDirectory(String projectSkillsDirectory) {\n\t\t\tthis.projectSkillsDirectory = projectSkillsDirectory;\n\t\t\treturn this;\n\t\t}\n\n\t\t/**\n\t\t * Set the project skills directory from a Spring Resource.","sourceCodeStart":302,"sourceCodeEnd":338,"githubUrl":"https://github.com/alibaba/spring-ai-alibaba/blob/f82da0b50f35744c13968191be2b1cd2452ef550/spring-ai-alibaba-graph-core/src/main/java/com/alibaba/cloud/ai/graph/skills/SpringAiSkillAdvisor.java#L302-L338","documentation":"SpringAiSkillAdvisor.Builder.userSkillsDirectory(Resource) calls resource.getFile(), which only works for file-system-backed Spring Resources; when conversion throws IOException the builder rethrows it as IllegalArgumentException. Classpath resources inside a JAR or remote resources cannot be converted to a file path.","triggerScenarios":"Passing a Resource that is not backed by a real file (e.g. ClassPathResource pointing into a packaged JAR, ByteArrayResource, UrlResource) to userSkillsDirectory(...).","commonSituations":"Skills bundled in a Spring Boot fat JAR where classpath resources are jar: URLs, not files; running from Docker image without exploded classes; devtools vs packaged behavior differences.","solutions":["Point userSkillsDirectory at an exploded directory on disk instead of a classpath/JAR resource","Unpack skill resources at startup to a temp directory and pass that path","Load skills via ClasspathSkillRegistry, which handles JAR-packaged skills","Ensure the Resource resolves to a real file (resource.getFile() must succeed)"],"exampleFix":"// before\nadvisor.builder().userSkillsDirectory(new ClassPathResource(\"skills\"));\n// after\nadvisor.builder().userSkillsDirectory(new FileSystemResource(\"/opt/app/skills\"));","handlingStrategy":"fallback","validationCode":"Resource r = new ClassPathResource(\"skills\");\nboolean usable = r.exists();\ntry { r.getFile(); } catch (IOException e) { usable = false; } // jar resources fail here","typeGuard":"boolean isFileBacked(Resource r) { try { return r != null && r.exists() && r.getFile().isFile(); } catch (IOException e) { return false; } }","tryCatchPattern":"try { builder.userSkillsDirectory(resource); } catch (IllegalArgumentException e) { log.warn(\"Resource not file-backed, falling back to classpath registry\"); }","preventionTips":["Never pass classpath resources from a fat JAR to directory-based setters","Extract packaged skills to a temp dir at startup for file-based access","Use ClasspathSkillRegistry when skills ship inside the application JAR","Test with the packaged (java -jar) artifact, not only the IDE run"],"tags":["spring","resource","filesystem"],"backgroundTag":"incompatible-source-type","analyzedSha":"f82da0b50f35744c13968191be2b1cd2452ef550","analyzedAt":"2026-09-09T15:32:42.421Z","contentChangedAt":"2026-09-09T15:32:42.421Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}