quarkusio/quarkus · error · GradleException

Failed to delete file:

Error message

Failed to delete file: 

What it means

CustomFileSystemOperations.deleteFileIfExists wraps Files.deleteIfExists; any IOException (e.g. file locked or in use) is rethrown as GradleException 'Failed to delete file: <path>'. It's used when the copy/sync operation must remove an existing destination file that is not writable before overwriting it.

Solutions

  1. Close processes holding the file (stop the running Quarkus app, dev mode, IDE indexing) then retry.
  2. Check and fix permissions: ensure the destination directory is writable by the build user.
  3. On Windows, reboot or use handle.exe to find the locker; exclude the build dir from antivirus.
  4. Free the mount if the destination is on a read-only filesystem.
Defensive patterns

Strategy: try-catch

Validate before calling

Path dest = ...;
File dir = dest.getParent().toFile();
if (Files.exists(dest) && !Files.isWritable(dest)) throw new IllegalStateException("dest not writable: " + dest);
if (!dir.canWrite()) throw new IllegalStateException("dest dir not writable: " + dir);

Try / catch

try {
    ./gradlew build
} catch (GradleException e) {
    if (e.getMessage().startsWith("Failed to delete file:")) {
        Path locked = Paths.get(e.getMessage().replace("Failed to delete file: ", ""));
        // stop the process holding it, chmod, or clear read-only mount, then retry
    }
}

Prevention

When it happens

Trigger: Executing a Quarkus copy/sync Gradle operation where an existing destination file must be deleted but Files.deleteIfExists throws IOException — destination file is locked by another process (IDE, running app, antivirus on Windows), read-only filesystem, or insufficient permissions on the parent directory.

Common situations: Windows: destination jar/classes locked by a running application or file indexer; Linux: read-only volume mount; destination inside a directory owned by another user; a previously failed build left immutable files.

Related errors


AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05). Data as JSON: /api/errors/5bb29a8fc53e2f88. Report an issue: GitHub.

Appendix: source

Thrown at devtools/gradle/gradle-application-plugin/src/main/java/io/quarkus/gradle/util/CustomFileSystemOperations.java:167

     * Deletes files and directories.
     *
     * @param action the delete action configuration
     * @return the result of the delete operation
     */
    public WorkResult delete(Action<? super DeleteSpec> action) {
        return getFs().delete(action);
    }

    /**
     * Deletes a file if it exists.
     *
     * @param file the file to delete
     */
    public static void deleteFileIfExists(Path file) {
        try {
            Files.deleteIfExists(file);
        } catch (IOException e) {
            throw new GradleException("Failed to delete file: " + file, e);
        }
    }

    private static void configureCopyOrSyncOperation(CopySpec copy, CopySyncConfiguration config,
            List<CopiedFileMetadata> copiedFilesMetadata) {
        // iterate over sources to be able to pass each source path to the TimestampPreservingCopyAction
        for (Path src : config.sources) {
            copy.from(src, spec -> spec.eachFile(
                    new TimestampPreservingCopyAction(
                            src,
                            config.destination,
                            copiedFilesMetadata)));
        }

        copy.into(config.destination);

        if (!config.includes.isEmpty()) {
            copy.include(config.includes);

View on GitHub (pinned to e1c734241f)