{"record":{"id":"9aa761ba141374cf","repo":"didi/DoKit","slug":"file-does-not-exist","errorCode":null,"errorMessage":"File does not exist: {}","messagePattern":"File does not exist: (.+?)","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"Android/dokit-leakcanary/src/main/java/com/squareup/leakcanary/HeapAnalyzer.java","lineNumber":90,"sourceCode":"        this.listener = listener;\n\n        this.reachabilityInspectors = new ArrayList<>();\n        for (Class<? extends Reachability.Inspector> reachabilityInspectorClass\n                : reachabilityInspectorClasses) {\n            try {\n                Constructor<? extends Reachability.Inspector> defaultConstructor =\n                        reachabilityInspectorClass.getDeclaredConstructor();\n                reachabilityInspectors.add(defaultConstructor.newInstance());\n            } catch (Exception e) {\n                throw new RuntimeException(e);\n            }\n        }\n    }\n\n    public @NonNull\n    List<TrackedReference> findTrackedReferences(@NonNull File heapDumpFile) {\n        if (!heapDumpFile.exists()) {\n            throw new IllegalArgumentException(\"File does not exist: \" + heapDumpFile);\n        }\n        try {\n            HprofBuffer buffer = new MemoryMappedFileBuffer(heapDumpFile);\n            HprofParser parser = new HprofParser(buffer);\n            Snapshot snapshot = parser.parse();\n            deduplicateGcRoots(snapshot);\n\n            ClassObj refClass = snapshot.findClass(KeyedWeakReference.class.getName());\n            List<TrackedReference> references = new ArrayList<>();\n            for (Instance weakRef : refClass.getInstancesList()) {\n                List<ClassInstance.FieldValue> values = HahaHelper.classInstanceValues(weakRef);\n                String key = HahaHelper.asString(HahaHelper.fieldValue(values, \"key\"));\n                String name =\n                        HahaHelper.hasField(values, \"name\") ? HahaHelper.asString(HahaHelper.fieldValue(values, \"name\")) : \"(No name field)\";\n                Instance instance = HahaHelper.fieldValue(values, \"referent\");\n                if (instance != null) {\n                    String className = getClassName(instance);\n                    List<LeakReference> fields = describeFields(instance);","sourceCodeStart":72,"sourceCodeEnd":108,"githubUrl":"https://github.com/didi/DoKit/blob/626827cddb2feb2f3aee87a52a064b4e5ca2bed4/Android/dokit-leakcanary/src/main/java/com/squareup/leakcanary/HeapAnalyzer.java#L72-L108","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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"],"exampleFix":"// before\nheapAnalyzer.findTrackedReferences(heapDumpFile);\n\n// after\nif (heapDumpFile == null || !heapDumpFile.exists() || !heapDumpFile.canRead()) {\n  throw new IllegalArgumentException(\"Heap dump missing: \" + heapDumpFile);\n}\nheapAnalyzer.findTrackedReferences(heapDumpFile);","handlingStrategy":"validation","validationCode":"if (heapDumpFile != null && heapDumpFile.exists() && heapDumpFile.canRead()) { heapAnalyzer.findTrackedReferences(heapDumpFile); }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Analyze a copy in app-private storage made right after capture","Beware of heap-dump pruning (maxStoredHeapDumps) deleting files before async analysis runs"],"tags":["leakcanary","heap-dump","file-io","android","java"],"backgroundTag":null,"analyzedSha":"626827cddb2feb2f3aee87a52a064b4e5ca2bed4","analyzedAt":"2026-08-14T12:45:58.758Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}