{"record":{"id":"0faf53b99b0acbef","repo":"shwenzhang/AndResGuard","slug":"now-can-only-proguard-less-than-35594-in-a-single-type","errorCode":null,"errorMessage":"now can only proguard less than 35594 in a single type\n","messagePattern":"now can only proguard less than 35594 in a single type\n","errorType":"exception","errorClass":"brut.androlib.AndrolibException","httpStatus":null,"severity":"error","filePath":"AndResGuard-core/src/main/java/com/tencent/mm/androlib/res/decoder/ARSCDecoder.java","lineNumber":1198,"sourceCode":"    public boolean isReplaced(int id) {\n      return mIsReplaced.contains(id);\n    }\n\n    public boolean isInWhiteList(int id) {\n      return mIsWhiteList.contains(id);\n    }\n\n    public void setInWhiteList(int id) {\n      mIsWhiteList.add(id);\n    }\n\n    public void setInReplaceList(int id) {\n      mIsReplaced.add(id);\n    }\n\n    public String getReplaceString() throws AndrolibException {\n      if (mReplaceStringBuffer.isEmpty()) {\n        throw new AndrolibException(String.format(\"now can only proguard less than 35594 in a single type\\n\"));\n      }\n      return mReplaceStringBuffer.remove(0);\n    }\n  }\n}","sourceCodeStart":1180,"sourceCodeEnd":1203,"githubUrl":"https://github.com/shwenzhang/AndResGuard/blob/e4df245d82f27d9a2d0dd108260a3510cbaba849/AndResGuard-core/src/main/java/com/tencent/mm/androlib/res/decoder/ARSCDecoder.java#L1180-L1203","documentation":"ARSCDecoder's proguard string pool pre-generates a fixed buffer (mReplaceStringBuffer) of short replacement resource names (roughly 35,594 entries, 0x8b0a limit imposed by arsc string encoding constraints). When more resource entries in a single type need replacement names than the buffer holds, getReplaceString finds it empty and throws. It is a hard capacity limit of the obfuscator, not a corruption error.","triggerScenarios":"A single resource type in the APK contains >= ~35594 entries, exhausting the pre-built replacement-name pool when each entry requests a new obfuscated name via getReplaceString().","commonSituations":"Extremely large apps (often merged/super apps or apps with many generated resources) with tens of thousands of drawables/layouts/strings in one type.","solutions":["Split resources into additional types/packages or use resource shrinking (remove unused resources) to get under the ~35594-per-type limit","Enable R8/ProGuard resource shrinking and remove unused drawables before obfuscating","Move bulk resources into a separate dynamic-feature/library module with its own package","Upgrade AndResGuard in case newer releases raise or parameterize the limit"],"exampleFix":"// before: 40000 drawables in one type\n// after: enable shrinking in build.gradle\nandroid {\n  buildTypes {\n    release {\n      minifyEnabled true\n      shrinkResources true\n    }\n  }\n}","handlingStrategy":"validation","validationCode":"// count entries per resource type before running obfuscation\nlong drawables = countEntriesOfType(apk, \"drawable\");\nif (drawables >= 35594) {\n  throw new GradleException(\"Type 'drawable' has \" + drawables + \" entries; shrink below 35594 or split packages\");\n}","typeGuard":null,"tryCatchPattern":"try {\n  andResGuardTask.execute();\n} catch (AndrolibException e) {\n  if (e.getMessage().contains(\"35594\")) {\n    throw new GradleException(\"Too many resources in a single type — shrink resources or split modules\", e);\n  }\n  throw e;\n}","preventionTips":["Enable shrinkResources + minifyEnabled in release builds","Remove unused/generated drawables before obfuscation","Split very large apps into feature/dynamic modules","Alert in CI when any resource type approaches ~35k entries"],"tags":["android","resource-obfuscation","capacity-limit","large-apps"],"backgroundTag":"value-out-of-range","analyzedSha":"e4df245d82f27d9a2d0dd108260a3510cbaba849","analyzedAt":"2026-09-12T17:49:07.798Z","contentChangedAt":"2026-09-12T17:49:07.798Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}