didi/DoKit · error · IllegalArgumentException
File does not exist: {}
Error message
File does not exist: {} What it means
HeapAnalyzer.findTrackedReferences() lists all watched references recorded in a heap dump file. Before parsing it validates that the .hprof file actually exists on disk, failing fast with IllegalArgumentException instead of letting the underlying MemoryMappedFileBuffer throw an opaque FileNotFoundException/IOException.
Source
Thrown at Android/dokit-leakcanary/src/main/java/com/squareup/leakcanary/HeapAnalyzer.java:90
this.listener = listener;
this.reachabilityInspectors = new ArrayList<>();
for (Class<? extends Reachability.Inspector> reachabilityInspectorClass
: reachabilityInspectorClasses) {
try {
Constructor<? extends Reachability.Inspector> defaultConstructor =
reachabilityInspectorClass.getDeclaredConstructor();
reachabilityInspectors.add(defaultConstructor.newInstance());
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
public @NonNull
List<TrackedReference> findTrackedReferences(@NonNull File heapDumpFile) {
if (!heapDumpFile.exists()) {
throw new IllegalArgumentException("File does not exist: " + heapDumpFile);
}
try {
HprofBuffer buffer = new MemoryMappedFileBuffer(heapDumpFile);
HprofParser parser = new HprofParser(buffer);
Snapshot snapshot = parser.parse();
deduplicateGcRoots(snapshot);
ClassObj refClass = snapshot.findClass(KeyedWeakReference.class.getName());
List<TrackedReference> references = new ArrayList<>();
for (Instance weakRef : refClass.getInstancesList()) {
List<ClassInstance.FieldValue> values = HahaHelper.classInstanceValues(weakRef);
String key = HahaHelper.asString(HahaHelper.fieldValue(values, "key"));
String name =
HahaHelper.hasField(values, "name") ? HahaHelper.asString(HahaHelper.fieldValue(values, "name")) : "(No name field)";
Instance instance = HahaHelper.fieldValue(values, "referent");
if (instance != null) {
String className = getClassName(instance);
List<LeakReference> fields = describeFields(instance);View on GitHub (pinned to 626827cddb)
Solutions
- Check heapDumpFile.exists() and heapDumpFile.canRead() before calling findTrackedReferences
- Copy the heap dump to a private, controlled location (context.getExternalFilesDir or cacheDir) immediately after capture and analyze the copy
- If the file was pruned, re-trigger the heap dump rather than analyzing a stale path
Example fix
// before
heapAnalyzer.findTrackedReferences(heapDumpFile);
// after
if (heapDumpFile == null || !heapDumpFile.exists() || !heapDumpFile.canRead()) {
throw new IllegalArgumentException("Heap dump missing: " + heapDumpFile);
}
heapAnalyzer.findTrackedReferences(heapDumpFile); Defensive patterns
Strategy: validation
Validate before calling
if (heapDumpFile != null && heapDumpFile.exists() && heapDumpFile.canRead()) { heapAnalyzer.findTrackedReferences(heapDumpFile); } Prevention
- Analyze a copy in app-private storage made right after capture
- Beware of heap-dump pruning (maxStoredHeapDumps) deleting files before async analysis runs
When it happens
Trigger: Calling heapAnalyzer.findTrackedReferences(heapDumpFile) with a File path that has been deleted, was never written (heap dump write failed or was cleaned by the LeakDirectoryProvider prune), or points to external storage that is unavailable (unmounted, permission-restricted scoped storage).
Common situations: Processing a heap dump asynchronously after the OS or the app itself deleted it (maxStoredHeapDumps pruning, cache cleanup, user clearing storage). Wrong file path construction (missing directory prefix). Android 10+ scoped storage restricting access to the expected location.
Related errors
- Could not find char array in {}
- Could not find the {} class in the heap dump.
- Could not find weak reference with key {} in {}
- leakTraceAsFakeException() can only be called when leakFound
- buildAndInstall() should only be called once.
AI-assisted analysis of didi/DoKit@626827cddb (2026-08-14).
Data as JSON: /api/errors/9aa761ba141374cf.
Report an issue: GitHub.