{"record":{"id":"290889ee3216e1c2","repo":"shwenzhang/AndResGuard","slug":"spec-proguard-name-duplicate-in-a-singal-type-s-spec-name-s","errorCode":null,"errorMessage":"spec proguard name duplicate in a singal type %s, spec name: %s\n","messagePattern":"spec proguard name duplicate in a singal type (.+?), spec name: (.+?)\n","errorType":"exception","errorClass":"brut.androlib.AndrolibException","httpStatus":null,"severity":"error","filePath":"AndResGuard-core/src/main/java/com/tencent/mm/androlib/res/data/ResType.java","lineNumber":40,"sourceCode":"public final class ResType {\n  private final String mName;\n\n  private final ResPackage mPackage;\n  private final HashSet<String> specNames;\n\n  public ResType(String name, ResPackage package_) {\n    this.mName = name;\n    this.mPackage = package_;\n    specNames = new HashSet<>();\n  }\n\n  public String getName() {\n    return mName;\n  }\n\n  public void putSpecResguardName(String name) throws AndrolibException {\n    if (specNames.contains(name)) {\n      throw new AndrolibException(String.format(\n          \"spec proguard name duplicate in a singal type %s, spec name: %s\\n\",\n          getName(),\n          name\n      ));\n    }\n    specNames.add(name);\n  }\n\n  @Override\n  public String toString() {\n    return mName;\n  }\n}\n","sourceCodeStart":22,"sourceCodeEnd":54,"githubUrl":"https://github.com/shwenzhang/AndResGuard/blob/e4df245d82f27d9a2d0dd108260a3510cbaba849/AndResGuard-core/src/main/java/com/tencent/mm/androlib/res/data/ResType.java#L22-L54","documentation":"ResType.putSpecResguardName throws this AndrolibException when the same proguard-resguard name is registered twice for one resource type. AndResGuard keeps a per-type set (specNames) of generated short names and requires them to be unique so obfuscated resource names do not collide in resources.arsc.","triggerScenarios":"Calling putSpecResguardName(name) on a ResType that already contains that exact name — typically from a custom resguard naming strategy (whiteList / package renaming) that maps two resources in the same type to the same short name, or re-running the name-allocation code on already-populated ResType objects.","commonSituations":"Custom resource name mapping files with duplicate entries for one type; colliding whitelist entries; reusing ResType instances across two obfuscation runs without clearing specNames; non-deterministic name generator producing repeats.","solutions":["Find the duplicate mapping for the printed type and spec name and make names unique within that type.","Deduplicate input mapping/whitelist entries before feeding them to AndResGuard.","If running obfuscation twice, recreate ResType objects instead of reusing populated ones.","If this is an intentional overwrite, check the set with contains() first and skip instead of adding."],"exampleFix":"// before\nresType.putSpecResguardName(\"a\");\nresType.putSpecResguardName(\"a\"); // throws\n// after\nif (!usedNames.contains(\"a\")) {\n    resType.putSpecResguardName(\"a\");\n}","handlingStrategy":"validation","validationCode":"Set<String> seen = new HashSet<>();\nfor (String name : newNames) {\n    if (!seen.add(name)) {\n        throw new IllegalArgumentException(\"duplicate resguard name: \" + name);\n    }\n}","typeGuard":null,"tryCatchPattern":"try {\n    resType.putSpecResguardName(name);\n} catch (AndrolibException e) {\n    // duplicate name in this type: regenerate or skip\n}","preventionTips":["Deduplicate mapping and whitelist files before obfuscation.","Use a deterministic, unique name generator per type.","Never reuse populated ResType instances across runs."],"tags":["resource-obfuscation","duplicate","naming"],"backgroundTag":"invalid-identifier-format","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"}