alibaba/spring-ai-alibaba · error · RuntimeException

Failed to delete JAR file: <jarPath>

Error message

Failed to delete JAR file: <jarPath>

What it means

Thrown by FileUtils.deleteResourceJarFromWorkDir when deleting a specific JAR file from the working directory fails with an IOException. The message includes the path of the JAR that could not be deleted; commonly the file is locked by a running JVM or another process.

Source

Thrown at spring-boot-starters/spring-ai-alibaba-starter-builtin-nodes/src/main/java/com/alibaba/cloud/ai/graph/utils/FileUtils.java:162

			});
		}
	}

	/**
	 * Deletes all JAR files from the specified working directory.
	 * @param workDir The working directory from which the JAR files will be deleted.
	 */
	public static void deleteResourceJarFromWorkDir(String workDir) {
		try {
			Path workDirPath = Path.of(workDir);
			if (Files.exists(workDirPath)) {
				try (var stream = Files.walk(workDirPath)) {
					stream.filter(path -> path.toString().endsWith(".jar")).forEach(jarPath -> {
						try {
							Files.deleteIfExists(jarPath);
						}
						catch (IOException e) {
							throw new RuntimeException("Failed to delete JAR file: " + jarPath, e);
						}
					});
				}
			}
		}
		catch (IOException e) {
			throw new RuntimeException("Failed to delete JAR files from working directory", e);
		}
	}

}

View on GitHub (pinned to f82da0b50f)

Solutions

  1. Close classloaders or stop processes that loaded JARs from the working directory before cleanup.
  2. Check the wrapped IOException cause (access denied vs file in use) for the OS-level reason.
  3. Ensure the process has delete permission on the working directory.
  4. On Windows, exclude JARs still in use, or schedule deletion for application shutdown.

Example fix

// before: delete everything while JVM still holds locks
stream.filter(p -> p.toString().endsWith(".jar")).forEach(p -> Files.deleteIfExists(p));
// after: tolerate locked files and log instead of failing the whole walk
stream.filter(p -> p.toString().endsWith(".jar")).forEach(p -> {
    try {
        Files.deleteIfExists(p);
    } catch (IOException e) {
        logger.warn("Could not delete locked JAR {}: {}", p, e.getMessage());
    }
});
Defensive patterns

Strategy: try-catch

Validate before calling

if (!Files.isDirectory(workDir)) return; // nothing to clean
try (var stream = Files.walk(workDir)) {
    boolean anyJar = stream.anyMatch(p -> p.toString().endsWith(".jar"));
}

Try / catch

try {
    FileUtils.deleteResourceJarFromWorkDir();
} catch (RuntimeException e) {
    logger.warn("JAR cleanup skipped: {}", e.getCause() != null ? e.getCause().getMessage() : e.getMessage());
}

Prevention

When it happens

Trigger: Files.deleteIfExists(jarPath) fails during the walk — typically because the JAR is currently loaded/locked by the JVM, held open by another process, or the directory entry cannot be removed due to permissions.

Common situations: Trying to clean up working-dir JARs while the application still has classloaders pointing at them; Windows file locking; insufficient filesystem permissions in shared containers.

Understand the failure class

Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.

Related errors


AI-assisted analysis of alibaba/spring-ai-alibaba@f82da0b50f (2026-09-09). Data as JSON: /api/errors/a2ee9e5352f3dd32. Report an issue: GitHub.