shwenzhang/AndResGuard · error · brut.androlib.AndrolibException
Config size < 28
Error message
Config size < 28
What it means
ARSCDecoder.readConfigFlags reads a resource table TYPE config structure and validates that its declared size is at least 28 bytes, the minimum defined by the Android resources.arsc format (ResTable_config header). A size smaller than 28 means the arsc chunk is malformed, truncated, or produced by a non-standard tool, so decoding cannot continue safely.
Solutions
- Rebuild the APK's resources.arsc with the official aapt/aapt2 from the Android SDK and re-run AndResGuard
- Verify the input APK is a valid, unmodified APK (aapt dump badging) before obfuscation
- Upgrade AndResGuard to the latest version, which tolerates more arsc variants
- If the arsc is intentionally non-standard, exclude it from processing or use --dont混淆 arsc options
Example fix
// before: decoding an APK compiled with a non-standard tool AndResGuard.process(apkFile); // after: rebuild resources with standard aapt2 first // ./gradlew assembleRelease (aapt2-produced arsc) AndResGuard.process(apkFile);
Defensive patterns
Strategy: try-catch
Validate before calling
// java
File arsc = extractArsc(apk);
long len = arsc.length();
if (len < 8 || !isPlausibleArsc(arsc)) throw new IllegalArgumentException("resources.arsc looks malformed"); Type guard
boolean isPlausibleArsc(File f) throws IOException {
try (DataInputStream in = new DataInputStream(new BufferedInputStream(new FileInputStream(f)))) {
int type = in.readUnsignedShort();
int size = in.readInt();
return type == 0x0002 && size > 28; // RES_TABLE_TYPE with sane header
}
} Try / catch
try {
arscDecoder.decode(arscStream);
} catch (AndrolibException e) {
if (e.getMessage().contains("Config size < 28")) {
// fail fast: rebuild apk with aapt2; do not retry on the same input
throw new BuildException("Malformed resources.arsc — rebuild with official aapt/aapt2", e);
}
throw e;
} Prevention
- Only feed AndResGuard APKs built with official aapt/aapt2
- Never double-process already obfuscated APKs
- Run aapt dump resources as a pre-build sanity check
- Keep AndResGuard up to date
When it happens
Trigger: Called during ARSC decode when iterating type configs: mIn.readInt() yields a config size < 28, i.e. the aapt-generated resources.arsc contains a ResTable_type entry with an undersized config header, or the stream is misaligned from earlier bad parsing.
Common situations: Processing an APK whose resources.arsc was built or rewritten by non-aapt tools (obfuscators, repackers), corrupted/truncated arsc files, or APKs from unusual build pipelines; also happens when a previous chunk was misread so the decoder reads garbage as the size field.
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.
Related errors
- Config size < 28
- Could not decode arsc file
- Invalid chunk type: expected=0x%08x, got=0x%08x
- Invalid chunk type: expected=
- readAndWriteHeader size < 0: size=
AI-assisted analysis of shwenzhang/AndResGuard@e4df245d82 (2026-09-12).
Data as JSON: /api/errors/5567f9b2ab52146f.
Report an issue: GitHub.
Appendix: source
Thrown at AndResGuard-core/src/main/java/com/tencent/mm/androlib/res/decoder/ARSCDecoder.java:852
return filterInfo;
}
private void writeValue() throws IOException, AndrolibException {
/* size */
mOut.writeCheckShort(mIn.readShort(), (short) 8);
/* zero */
mOut.writeCheckByte(mIn.readByte(), (byte) 0);
byte type = mIn.readByte();
mOut.writeByte(type);
int data = mIn.readInt();
mOut.writeInt(data);
}
private void readConfigFlags() throws IOException, AndrolibException {
int size = mIn.readInt();
int read = 28;
if (size < 28) {
throw new AndrolibException("Config size < 28");
}
boolean isInvalid = false;
short mcc = mIn.readShort();
short mnc = mIn.readShort();
char[] language = new char[] { (char) mIn.readByte(), (char) mIn.readByte() };
char[] country = new char[] { (char) mIn.readByte(), (char) mIn.readByte() };
byte orientation = mIn.readByte();
byte touchscreen = mIn.readByte();
int density = mIn.readUnsignedShort();
byte keyboard = mIn.readByte();
byte navigation = mIn.readByte();
byte inputFlags = mIn.readByte();View on GitHub (pinned to e4df245d82)