nostra13/Android-Universal-Image-Loader · error · IOException
failed to delete file: {file}
Error message
failed to delete file: {file} What it means
Thrown by Util.deleteContents when File.delete() returns false for an entry inside the cache directory while the LruDiskCache (DiskLruCache) is clearing its directory during initialization or maintenance. It means the OS refused the delete: the file is locked by another process/handle, the directory entry is read-only, or the filesystem is in a bad state. Because deleteContents recurses depth-first, the offending nested File is included in the message.
Source
Thrown at library/src/main/java/com/nostra13/universalimageloader/cache/disc/impl/ext/Util.java:61
reader.close();
}
}
/**
* Deletes the contents of {@code dir}. Throws an IOException if any file
* could not be deleted, or if {@code dir} is not a readable directory.
*/
static void deleteContents(File dir) throws IOException {
File[] files = dir.listFiles();
if (files == null) {
throw new IOException("not a readable directory: " + dir);
}
for (File file : files) {
if (file.isDirectory()) {
deleteContents(file);
}
if (!file.delete()) {
throw new IOException("failed to delete file: " + file);
}
}
}
static void closeQuietly(/*Auto*/Closeable closeable) {
if (closeable != null) {
try {
closeable.close();
} catch (RuntimeException rethrown) {
throw rethrown;
} catch (Exception ignored) {
}
}
}
}View on GitHub (pinned to ba33ec64d0)
Solutions
- Use a private, per-process cache directory (context.getCacheDir() based) so nothing else holds handles to files in it
- Ensure only one ImageLoader instance/process owns the disk cache directory
- Free storage / remount the volume writable, then restart the app
- Catch IOException around ImageLoader init and continue with memory-cache-only configuration
Example fix
// before
ImageLoader.getInstance().init(config); // crashes stack with failed to delete file: ...
// after
try {
ImageLoader.getInstance().init(config);
} catch (IOException e) {
L.e("disk cache unusable, falling back", e);
ImageLoader.getInstance().init(new ImageLoaderConfiguration.Builder(context)
.memoryCacheSizePercentage(25)
.build()); // no disk cache
} Defensive patterns
Strategy: fallback
Validate before calling
boolean canWrite = cacheDir.canWrite();
// best-effort probe: try deleting a temp file
File probe = new File(cacheDir, ".probe");
try {
if (probe.createNewFile() && probe.delete()) canWrite = true; else canWrite = false;
} catch (IOException e) { canWrite = false; } Try / catch
try {
ImageLoader.getInstance().init(config);
} catch (IOException e) {
L.e("disk cache init failed: " + e.getMessage(), e);
ImageLoader.getInstance().init(memoryOnlyConfig);
} Prevention
- Keep the disk cache in app-private storage owned solely by your process
- Initialize ImageLoader in Application.onCreate and catch IOException there to degrade gracefully
- Monitor free storage; a full read-only volume is a common root cause
When it happens
Trigger: DiskLruCache initialization calling deleteContents(directory) on a cache dir containing undeletable entries: a file currently open by another thread/process, read-only media, or a file created by a different app uid in a shared cache path.
Common situations: Two app processes sharing one external-storage cache directory; a crash left a partially-written journal and a stale file handle; SD card mounted read-only or full; OEM storage quirks; antivirus/adb pulling files out of the cache dir while the app starts.
Related errors
- failed to delete {file}
- not a readable directory: {dir}
- unexpected journal header: [{magic}, {version}, {valueCountS
- unexpected journal line: {line}
- unexpected journal line: {strings}
AI-assisted analysis of nostra13/Android-Universal-Image-Loader@ba33ec64d0 (2026-08-14).
Data as JSON: /api/errors/07a1cb641f4cd855.
Report an issue: GitHub.