shwenzhang/AndResGuard · error · brut.androlib.AndrolibException
readEntry replaceString == null
Error message
readEntry replaceString == null
What it means
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.
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.
Example fix
// before (gradle) apply plugin: 'AndResGuard' // old 1.2.x with AGP 4.x APKs // after classpath 'com.tencent.mm:AndResGuard-gradle-plugin:1.2.21' // supports modern aapt2 output
Defensive patterns
Strategy: try-catch
Try / catch
try {
ResPackage[] pkgs = ARSCDecoder.decode(arscStream, apkDecoder);
} catch (AndrolibException e) {
if (e.getMessage().contains("replaceString == null")) {
// arsc format unsupported by this AndResGuard version: upgrade plugin
}
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- can not find \ or raw string in res path =
- Could not decode arsc file
- the old mapping res file path should be like r/a, yours
- writeTable package count is different before
- writeEntry new specNamesId < 0
AI-assisted analysis of shwenzhang/AndResGuard@e4df245d82 (2026-09-12).
Data as JSON: /api/errors/dd48697622bd2c40.
Report an issue: GitHub.
Appendix: source
Thrown at AndResGuard-core/src/main/java/com/tencent/mm/androlib/res/decoder/ARSCDecoder.java:648
String typeName = mType.getName();
if (typeMaps.containsKey(typeName)) {
HashMap<String, String> nameMap = typeMaps.get(typeName);
String specName = mSpecNames.get(specNamesId).toString();
if (nameMap.containsKey(specName)) {
keepMapping = true;
replaceString = nameMap.get(specName);
}
}
}
}
if (!keepMapping) {
replaceString = mResguardBuilder.getReplaceString();
}
mResguardBuilder.setInReplaceList(mCurEntryID);
if (replaceString == null) {
throw new AndrolibException("readEntry replaceString == null");
}
generalResIDMapping(mPkg.getName(), mType.getName(), mSpecNames.get(specNamesId).toString(), replaceString);
mPkg.putSpecNamesReplace(mResId, replaceString);
// arsc name列混淆成固定名字, 减少string pool大小
boolean useFixedName = config.mFixedResName != null && config.mFixedResName.length() > 0;
String fixedName = useFixedName ? config.mFixedResName : replaceString;
mPkg.putSpecNamesblock(fixedName, replaceString);
mType.putSpecResguardName(replaceString);
}
private void writeEntry() throws IOException, AndrolibException {
/* size */
mOut.writeBytes(mIn, 2);
short flags = mIn.readShort();
mOut.writeShort(flags);
int specNamesId = mIn.readInt();
ResPackage pkg = mPkgs[mCurPackageID];
if (pkg.isCanResguard()) {View on GitHub (pinned to e4df245d82)