apache/cassandra · warning
Failed to delete {} on exit
Error message
Failed to delete {} on exit What it means
PathUtils registers a JVM shutdown hook (DeleteOnExit) that deletes files queued via deleteOnExitIfPossible(). If deleting a single queued file fails, it logs this warning with the path and the underlying cause. It is a best-effort cleanup notification, not a thrown error: the shutdown hook swallows the throwable and continues with the remaining queued paths.
Source
Thrown at src/java/org/apache/cassandra/io/util/PathUtils.java:737
{
isRegistered = true;
}
logger.trace("Scheduling deferred {}deletion of file: {}", recursive ? "recursive " : "", path);
(recursive ? deleteRecursivelyOnExit : deleteOnExit).add(path);
}
public void run()
{
for (Path path : deleteOnExit)
{
try
{
if (exists(path))
delete(path);
}
catch (Throwable t)
{
logger.warn("Failed to delete {} on exit", path, t);
}
}
for (Path path : deleteRecursivelyOnExit)
{
try
{
if (exists(path))
deleteRecursive(path);
}
catch (Throwable t)
{
logger.warn("Failed to delete {} on exit", path, t);
}
}
}
}
private static final DeleteOnExit ON_EXIT = new DeleteOnExit();
View on GitHub (pinned to 88fd0f6a0e)
Solutions
- Read the attached cause (t) to identify why delete failed (lock vs permissions vs race).
- Ensure resources holding the file (FileHandle, RandomAccessReader, mapped segments) are closed before shutdown.
- Remove the file explicitly during normal teardown instead of relying on delete-on-exit if it is recreated concurrently.
- On Windows, check for antivirus/backup processes locking the file.
- If harmless and recurring, suppress the specific path or downgrade handling since the JVM is exiting anyway.
Example fix
// before
File tmp = File.createTempFile("hints", ".tmp");
PathUtils.deleteOnExitIfPossible(tmp.toPath());
// after
File tmp = File.createTempFile("hints", ".tmp");
try (FileOutputStream out = new FileOutputStream(tmp)) { /* use */ }
PathUtils.delete(tmp.toPath()); // explicit deterministic cleanup instead of delete-on-exit Defensive patterns
Strategy: try-catch
Validate before calling
// before shutdown
if (!java.nio.file.Files.isWritable(path.getParent()))
logger.warn("Path {} will not be deletable on exit", path); Type guard
static boolean deletable(java.nio.file.Path p) {
return java.nio.file.Files.exists(p) && java.nio.file.Files.isWritable(p.getParent()) && !java.nio.file.Files.isDirectory(p);
} Try / catch
try { java.nio.file.Files.deleteIfExists(path); }
catch (java.io.IOException e) { logger.warn("Failed to delete {} on exit", path, e); } Prevention
- Close all file handles and mapped buffers before JVM exit (try-with-resources).
- Prefer explicit deterministic cleanup in application teardown over delete-on-exit.
- Check file writability/locks (esp. Windows AV scanners) for temp-file locations.
- Avoid recreating files queued for deletion during shutdown.
When it happens
Trigger: A path was queued with PathUtils.deleteOnExitIfPossible/deleteAsync; at JVM shutdown the hook runs and exists(path) is true but delete(path) throws (file locked, open memory-mapped segment, permission change, or the file was recreated/deleted concurrently between the exists() check and delete()).
Common situations: Commit-log/memtable segment files still mapped or held open by a lingering thread at shutdown; temp files in test teardown with stale file handles; directory whose permissions changed; on Windows, files locked by another process.
Related errors
- Exception thrown when cleaning up files to delete on exit, c
- Unable to clean up %s directory from empty %s files.
- Failed to delete {}
- Failed to remove hard link files
- Unable to delete storage-attached index component file {} du
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/3aa1339cca36f722.
Report an issue: GitHub.