{"record":{"id":"a86c73faee9d8e1c","repo":"alibaba/spring-ai-alibaba","slug":"failed-to-copy-jar-files-to-working-directory-a86c73","errorCode":null,"errorMessage":"Failed to copy JAR files to working directory","messagePattern":"Failed to copy JAR files to working directory","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"spring-boot-starters/spring-ai-alibaba-starter-builtin-nodes/src/main/java/com/alibaba/cloud/ai/graph/utils/FileUtils.java","lineNumber":121,"sourceCode":"\t\t\t\tif (\"file\".equals(libUrl.getProtocol())) {\n\t\t\t\t\tcopyJarFilesFromDir(Path.of(libUrl.toURI()), targetDir);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (\"jar\".equals(libUrl.getProtocol())) {\n\t\t\t\t\tString jarUrl = libUrl.toString();\n\t\t\t\t\tint separatorIndex = jarUrl.indexOf(\"!/\");\n\t\t\t\t\tif (separatorIndex <= 0) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tURI jarFileUri = URI.create(jarUrl.substring(0, separatorIndex));\n\t\t\t\t\ttry (FileSystem fs = FileSystems.newFileSystem(jarFileUri, Collections.emptyMap())) {\n\t\t\t\t\t\tcopyJarFilesFromDir(fs.getPath(\"/lib\"), targetDir);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tcatch (Exception e) {\n\t\t\tthrow new RuntimeException(\"Failed to copy JAR files to working directory\", e);\n\t\t}\n\t}\n\n\t/**\n\t * Copies all JAR files under the source directory to the target directory.\n\t * @param sourceDir The source directory containing JAR files.\n\t * @param targetDir The target directory where JAR files will be copied.\n\t * @throws IOException if I/O operations fail while scanning or copying files.\n\t */\n\tprivate static void copyJarFilesFromDir(Path sourceDir, Path targetDir) throws IOException {\n\t\tif (!Files.exists(sourceDir)) {\n\t\t\treturn;\n\t\t}\n\t\ttry (var stream = Files.walk(sourceDir)) {\n\t\t\tstream.filter(path -> path.toString().endsWith(\".jar\")).forEach(jarPath -> {\n\t\t\t\ttry {\n\t\t\t\t\tPath targetPath = targetDir.resolve(jarPath.getFileName().toString());\n\t\t\t\t\tFiles.copy(jarPath, targetPath, StandardCopyOption.REPLACE_EXISTING);","sourceCodeStart":103,"sourceCodeEnd":139,"githubUrl":"https://github.com/alibaba/spring-ai-alibaba/blob/f82da0b50f35744c13968191be2b1cd2452ef550/spring-boot-starters/spring-ai-alibaba-starter-builtin-nodes/src/main/java/com/alibaba/cloud/ai/graph/utils/FileUtils.java#L103-L139","documentation":"Thrown by FileUtils.copyResourceJarToWorkDir when any step of opening the resource JAR's filesystem, walking its /lib directory, or copying nested JARs into the working directory fails. It wraps the original exception (IOException, FileSystemNotFoundException, ProviderNotFoundException, etc.), so the cause chain is essential for diagnosis.","triggerScenarios":"Calling copyResourceJarToWorkDir with a resource location that cannot be opened as a zip/JAR filesystem (resource missing, classpath loaded via nested JAR without an unzip-capable FileSystemProvider, or target directory not writable).","commonSituations":"Running from a Spring Boot fat JAR where the resource JAR is nested inside another JAR; read-only filesystem or container without write permissions to the work dir; resource path typo in classpath configuration.","solutions":["Check the wrapped cause in the stack trace (IOException vs FileSystemNotFoundException) to identify the real failure.","Verify the resource JAR exists on the classpath and the path passed is correct.","Ensure the working directory exists and the process has write permission to it.","If running from a fat/nested JAR, extract the resource JAR to disk first or use an input-stream based copy instead of a zip FileSystem."],"exampleFix":"// before: relying on zipfs for a nested-jar resource\nPath jarFsPath = fs.getPath(\"/lib\");\ncopyJarFilesFromDir(jarFsPath, targetDir);\n// after: pre-flight validation of target dir and cause logging\ntargetDir = Files.createDirectories(targetDir);\ntry {\n    copyJarFilesFromDir(jarFsPath, targetDir);\n} catch (RuntimeException e) {\n    logger.error(\"JAR copy failed; targetDir={}, cause={}\", targetDir, e.getCause(), e);\n    throw e;\n}","handlingStrategy":"try-catch","validationCode":"Path targetDir = Path.of(workDir);\nif (!Files.isDirectory(targetDir)) Files.createDirectories(targetDir);\nif (!Files.isWritable(targetDir)) throw new IllegalStateException(\"Work dir not writable: \" + targetDir);","typeGuard":null,"tryCatchPattern":"try {\n    FileUtils.copyResourceJarToWorkDir();\n} catch (RuntimeException e) {\n    logger.error(\"JAR copy failed: {}\", e.getCause() != null ? e.getCause().toString() : e.getMessage(), e);\n}","preventionTips":["Log and inspect the wrapped cause chain — the real error is always in getCause().","Pre-create and permission-check the working directory before copying.","Avoid relying on this when running from nested/fat JARs; verify the resource is openable as a zip filesystem first."],"tags":["filesystem","io","classpath","jar"],"backgroundTag":"file-write-failed","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"}