{"record":{"id":"c5644b3188be0a9f","repo":"Tencent/matrix","slug":"could-not-find-weak-reference-with-key","errorCode":null,"errorMessage":"Could not find weak reference with key ","messagePattern":"Could not find weak reference with key ","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"warning","filePath":"matrix/matrix-android/matrix-resource-canary/matrix-resource-canary-analyzer/src/main/java/com/tencent/matrix/resource/analyzer/ActivityLeakAnalyzer.java","lineNumber":106,"sourceCode":"        if (infoClass == null) {\n            throw new IllegalStateException(\"Unabled to find destroy activity info class with name: \"\n                    + DESTROYED_ACTIVITY_INFO_CLASSNAME);\n        }\n        List<String> keysFound = new ArrayList<>();\n        for (Instance infoInstance : infoClass.getInstancesList()) {\n            final List<ClassInstance.FieldValue> values = classInstanceValues(infoInstance);\n            final String keyCandidate = asString(fieldValue(values, ACTIVITY_REFERENCE_KEY_FIELDNAME));\n            if (keyCandidate.equals(key)) {\n                final Instance weakRefObj = fieldValue(values, ACTIVITY_REFERENCE_FIELDNAME);\n                if (weakRefObj == null) {\n                    continue;\n                }\n                final List<ClassInstance.FieldValue> activityRefs = classInstanceValues(weakRefObj);\n                return fieldValue(activityRefs, \"referent\");\n            }\n            keysFound.add(keyCandidate);\n        }\n        throw new IllegalStateException(\n                \"Could not find weak reference with key \" + key + \" in \" + keysFound);\n    }\n\n    private ActivityLeakResult findLeakTrace(long analysisStartNanoTime, Snapshot snapshot,\n                                         Instance leakingRef) {\n\n        ShortestPathFinder pathFinder = new ShortestPathFinder(mExcludedRefs);\n        ShortestPathFinder.Result result = pathFinder.findPath(snapshot, leakingRef);\n\n        // False alarm, no strong reference path to GC Roots.\n        if (result.referenceChainHead == null) {\n            return ActivityLeakResult.noLeak(AnalyzeUtil.since(analysisStartNanoTime));\n        }\n\n        final ReferenceChain referenceChain = result.buildReferenceChain();\n        final String className = leakingRef.getClassObj().getClassName();\n        if (result.excludingKnown || referenceChain.isEmpty()) {\n            return ActivityLeakResult.noLeak(AnalyzeUtil.since(analysisStartNanoTime));","sourceCodeStart":88,"sourceCodeEnd":124,"githubUrl":"https://github.com/Tencent/matrix/blob/3b8293bd65d47eeea7caf1f32a3a5d4d5eab60e7/matrix/matrix-android/matrix-resource-canary/matrix-resource-canary-analyzer/src/main/java/com/tencent/matrix/resource/analyzer/ActivityLeakAnalyzer.java#L88-L124","documentation":"After finding DestroyedActivityInfo instances, the analyzer matches each instance's activity reference key against the requested key to locate the corresponding weak reference's referent. If every key candidate differs from the target key, no matching weak reference exists in the dump and it throws IllegalStateException listing all keys found.","triggerScenarios":"findLeakingReference is called with a key that was never registered in the heap dump — the activity was already GC'd (its weak reference cleared), the key was computed differently at capture vs. analysis time, or the analyzed dump corresponds to a different session.","commonSituations":"Analyzing a stale heap dump after the weakly-referenced activity was collected; key generation (UUID/activity name) changed between app versions; re-running analysis with a wrong key; the leak was a false alarm and GC reclaimed the activity.","solutions":["Re-capture the hprof immediately after the leak watch triggers so the weak reference is still present.","Verify the key passed to findLeakingReference matches the key used when the activity was destroyed (same key-generation logic/version).","Treat this as 'no leak — object was GC'd' and return a no-leak result instead of throwing.","Make sure the analyzed dump belongs to the same session that recorded the destroyed activity."],"exampleFix":"// before\nthrow new IllegalStateException(\"Could not find weak reference with key \" + key + \" in \" + keysFound);\n// after\nif (keysFound.isEmpty()) {\n    return null; // weak ref already cleared: not a leak\n}\nthrow new IllegalStateException(\"Could not find weak reference with key \" + key + \" in \" + keysFound);","handlingStrategy":"try-catch","validationCode":"// ensure the key was recorded when the activity was destroyed; verify dump session matches","typeGuard":null,"tryCatchPattern":"try { referent = findLeakingReference(key, snapshot); } catch (IllegalStateException e) { return ActivityLeakResult.noLeak(); /* weak ref likely cleared */ }","preventionTips":["Capture the hprof immediately when leak detection fires","Use stable, version-consistent key generation","Verify dump session matches the session that recorded the key"],"tags":["android","memory-leak","weak-reference","hprof"],"backgroundTag":"record-not-found","analyzedSha":"3b8293bd65d47eeea7caf1f32a3a5d4d5eab60e7","analyzedAt":"2026-09-08T08:01:39.722Z","contentChangedAt":"2026-09-08T08:01:39.722Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}