{"record":{"id":"9bcfde7d76ddc849","repo":"Tencent/matrix","slug":"found-resource-cycle-visitpath","errorCode":null,"errorMessage":"Found resource cycle! <visitPath>","messagePattern":"Found resource cycle! <visitPath>","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"matrix/matrix-android/matrix-apk-canary/src/main/java/com/tencent/matrix/apk/model/task/UnusedResourcesTask.java","lineNumber":464,"sourceCode":"        for (String pattern : ignoreSet) {\n            if (name.matches(pattern)) {\n                return true;\n            }\n        }\n        return false;\n    }\n\n    private void readChildReference(String resource) throws IllegalStateException {\n        if (nonValueReferences.containsKey(resource)) {\n            visitPath.push(resource);\n            Set<String> childReference = nonValueReferences.get(resource);\n            unusedResSet.removeAll(childReference);\n            for (String reference : childReference) {\n                if (!visitPath.contains(reference)) {\n                    readChildReference(reference);\n                } else {\n                    visitPath.push(reference);\n                    throw new IllegalStateException(\"Found resource cycle! \" + visitPath.toString());\n                }\n            }\n            visitPath.pop();\n        }\n    }\n\n\n    @Override\n    public TaskResult call() throws TaskExecuteException {\n        try {\n            TaskResult taskResult = TaskResultFactory.factory(type, TaskResultFactory.TASK_RESULT_TYPE_JSON, config);\n            long startTime = System.currentTimeMillis();\n            readMappingTxtFile();\n            readResourceTxtFile();\n            ResguardUtil.readResMappingTxtFile(resMappingTxt, null, resguardMap);\n            unusedResSet.addAll(resourceDefMap.values());\n            Log.i(TAG, \"find resource declarations %d items.\", unusedResSet.size());\n            decodeCode();","sourceCodeStart":446,"sourceCodeEnd":482,"githubUrl":"https://github.com/Tencent/matrix/blob/3b8293bd65d47eeea7caf1f32a3a5d4d5eab60e7/matrix/matrix-android/matrix-apk-canary/src/main/java/com/tencent/matrix/apk/model/task/UnusedResourcesTask.java#L446-L482","documentation":"During unused-resource reference resolution, readChildReference() does a DFS over the resource dependency graph and throws IllegalStateException when a resource references another resource already on the current visit path — i.e., a cycle. The message includes the cycle path stack for debugging.","triggerScenarios":"AAPT/resource definitions where resources reference each other cyclically (e.g., drawable A references drawable B which references A), encountered while recursively decoding resources.","commonSituations":"Exotic resource setups: vector drawables, drawables with theme attributes, or generated resources with mutual references; also triggered by unusual custom resource merging.","solutions":["Inspect the cycle path in the message and refactor one resource to break the cycle","Exclude the cyclic resources from analysis via the ignore-resources param (PARAM_IGNORE_RESOURCES_LIST)","Update Matrix — newer versions may treat cycles as terminal instead of throwing"],"exampleFix":"// gradle param\n// before\nparams: unused-resources without ignore list\n// after\nparams.put(JobConstants.PARAM_IGNORE_RESOURCES_LIST, \"drawable/cycle_a,drawable/cycle_b\");","handlingStrategy":"try-catch","validationCode":"// inspect the reported cycle path in the message before re-running\nString msg = e.getMessage(); // \"Found resource cycle! [a, b, a]\" — add these to ignore list","typeGuard":null,"tryCatchPattern":"try {\n    TaskResult r = task.call();\n} catch (Exception e) {\n    if (e.getMessage() != null && e.getMessage().startsWith(\"Found resource cycle!\")) {\n        // add cycle members to PARAM_IGNORE_RESOURCES_LIST and retry\n    } else {\n        throw e;\n    }\n}","preventionTips":["Avoid mutually-referencing resources (drawables/alias cycles)","Add known cyclic resources to the ignore-resources list","Keep Matrix updated for cycle-handling fixes"],"tags":["android","resources","graph-cycle"],"backgroundTag":"internal-invariant-violation","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"}