{"record":{"id":"dd48697622bd2c40","repo":"shwenzhang/AndResGuard","slug":"readentry-replacestring-null","errorCode":null,"errorMessage":"readEntry replaceString == null","messagePattern":"readEntry replaceString == null","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":648,"sourceCode":"        String typeName = mType.getName();\n        if (typeMaps.containsKey(typeName)) {\n          HashMap<String, String> nameMap = typeMaps.get(typeName);\n          String specName = mSpecNames.get(specNamesId).toString();\n          if (nameMap.containsKey(specName)) {\n            keepMapping = true;\n            replaceString = nameMap.get(specName);\n          }\n        }\n      }\n    }\n\n    if (!keepMapping) {\n      replaceString = mResguardBuilder.getReplaceString();\n    }\n\n    mResguardBuilder.setInReplaceList(mCurEntryID);\n    if (replaceString == null) {\n      throw new AndrolibException(\"readEntry replaceString == null\");\n    }\n    generalResIDMapping(mPkg.getName(), mType.getName(), mSpecNames.get(specNamesId).toString(), replaceString);\n    mPkg.putSpecNamesReplace(mResId, replaceString);\n    // arsc name列混淆成固定名字, 减少string pool大小\n    boolean useFixedName = config.mFixedResName != null && config.mFixedResName.length() > 0;\n    String fixedName = useFixedName ? config.mFixedResName : replaceString;\n    mPkg.putSpecNamesblock(fixedName, replaceString);\n    mType.putSpecResguardName(replaceString);\n  }\n\n  private void writeEntry() throws IOException, AndrolibException {\n    /* size */\n    mOut.writeBytes(mIn, 2);\n    short flags = mIn.readShort();\n    mOut.writeShort(flags);\n    int specNamesId = mIn.readInt();\n    ResPackage pkg = mPkgs[mCurPackageID];\n    if (pkg.isCanResguard()) {","sourceCodeStart":630,"sourceCodeEnd":666,"githubUrl":"https://github.com/shwenzhang/AndResGuard/blob/e4df245d82f27d9a2d0dd108260a3510cbaba849/AndResGuard-core/src/main/java/com/tencent/mm/androlib/res/decoder/ARSCDecoder.java#L630-L666","documentation":"While decoding a resource entry for obfuscation, readEntry obtains a replacement short name from the ResguardBuilder. If the replace string comes back null (no obfuscated name available for the current entry ID) AndResGuard throws, because every resguard-able entry must get a name for the arsc mapping.","triggerScenarios":"Decoding a resources.arsc whose entry ordering/IDs don't match what the ResguardBuilder precomputed — e.g. arsc format variants AAPT2 emits that the builder didn't account for, or entry/ID lists desynchronized so getReplaceString(mCurEntryID) has no entry at the current index.","commonSituations":"APKs built with newer AGP/AAPT2 versions than the AndResGuard release supports; arsc with unusual entry layouts (sparse entries, type/entry id offsets); protected/packed APKs with tampered arsc.","solutions":["Upgrade AndResGuard (and AGP/AndResGuard Gradle plugin) to the latest version — arsc compatibility fixes land frequently.","Rebuild the APK with standard AAPT2 and retry without other resource-processing tools applied first.","Check whether the APK's arsc uses unusual features (sparse entries, shared libraries); build with aaptOptions/noCompress defaults or flatten those features.","Report the failing APK's arsc structure to the AndResGuard maintainers if it still reproduces."],"exampleFix":"// before (gradle)\napply plugin: 'AndResGuard' // old 1.2.x with AGP 4.x APKs\n// after\nclasspath 'com.tencent.mm:AndResGuard-gradle-plugin:1.2.21' // supports modern aapt2 output","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n    ResPackage[] pkgs = ARSCDecoder.decode(arscStream, apkDecoder);\n} catch (AndrolibException e) {\n    if (e.getMessage().contains(\"replaceString == null\")) {\n        // arsc format unsupported by this AndResGuard version: upgrade plugin\n    }\n}","preventionTips":["Keep AndResGuard Gradle plugin and AGP versions current and compatible.","Apply AndResGuard to a plain assembleRelease APK, not one preprocessed by other tools.","Test resource obfuscation on release builds in CI to catch arsc compatibility early."],"tags":["arsc","obfuscation","aapt2","compatibility"],"backgroundTag":"internal-invariant-violation","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"}