skylot/jadx · error · IOException
Decode error: ${message}, position: 0x${position}
Error message
Decode error: ${message}, position: 0x${position} What it means
Thrown by CommonBinaryParser.die(String) as an IOException (not JadxRuntimeException) when the binary XML parser encounters a structural error in an Android binary XML resource (e.g., AndroidManifest.xml, layout XML). The message includes a human-readable reason and the current byte position (hex) in the stream. This is the parser's fatal-error signal for malformed or truncated binary XML chunks — used when expected magic numbers, chunk sizes, or string-pool boundaries don't match.
Source
Thrown at jadx-core/src/main/java/jadx/core/xmlgen/CommonBinaryParser.java:50
int styleCount = is.readInt32();
int flags = is.readInt32();
long stringsStart = is.readInt32();
long stylesStart = is.readInt32();
// Correct the offset of actual strings, as the header is already read.
stringsStart = stringsStart - (is.getPos() - start);
byte[] buffer = is.readInt8Array((int) (chunkEnd - is.getPos()));
is.checkPos(chunkEnd, "Expected strings pool end");
return new BinaryXMLStrings(
stringCount,
stringsStart,
buffer,
(flags & UTF8_FLAG) != 0);
}
protected void die(String message) throws IOException {
throw new IOException("Decode error: " + message
+ ", position: 0x" + Long.toHexString(is.getPos()));
}
}
View on GitHub (pinned to e738a26571)
Solutions
- Catch IOException around the parse() call and log the position for diagnosis.
- Re-download or re-obtain the APK from a trusted source to rule out truncation.
- Use apktool or aapt to validate the binary XML independently.
- If obfuscation is suspected, try --no-debug-info or relaxed parsing options in jadx.
Example fix
// before
ICodeInfo info = parser.parse(inputStream);
// after — catch the IOException and degrade gracefully
try {
ICodeInfo info = parser.parse(inputStream);
} catch (IOException e) {
LOG.warn("Binary XML parse failed: {}", e.getMessage());
// fall back to raw output or skip this resource
} Defensive patterns
Strategy: try-catch
Validate before calling
// No programmatic pre-validation possible for binary XML internals.
// Best effort: check the file starts with a binary XML magic number.
public static boolean looksLikeBinaryXml(byte[] header) {
// Android binary XML starts with 0x00080003 (little-endian: 03 00 08 00)
return header != null && header.length >= 4
&& header[0] == 0x03 && header[1] == 0x00
&& header[2] == 0x08 && header[3] == 0x00;
} Try / catch
try {
ICodeInfo info = parser.parse(inputStream);
} catch (IOException e) {
LOG.warn("Binary XML decode error at {}: {}", e.getMessage());
// degrade gracefully: skip resource or output raw bytes
} Prevention
- Validate the APK integrity before decompiling (checksum, aapt dump).
- Catch IOException around parse() and degrade gracefully for corrupted resources.
- Be cautious with packed/obfuscated APKs that may intentionally corrupt binary XML.
When it happens
Trigger: Parsing a binary Android XML resource that is corrupted, truncated, or not actually binary XML (wrong chunk type). A malformed string pool where chunkEnd doesn't align (is.checkPos fails). Invalid header sizes or magic values in the RES_STRING_POOL_TYPE check. Deliberately malformed XML from an obfuscator or packer.
Common situations: Decompiling a packed/obfuscated APK with intentionally corrupted resources.arsc or AndroidManifest.xml. A truncated APK download. A resource file that was processed by an aggressive resource shrinker/proguard. An anti-decompilation tool that corrupts binary XML headers.
Related errors
- BinaryXMLParser init error
- Xml load error, file: {}
- Bad name for type variable: {}
- Can't parse type: {}, unexpected: {}
- No inner type found: {}
AI-assisted analysis of skylot/jadx@e738a26571 (2026-08-14).
Data as JSON: /api/errors/c66c2282e6be8dd4.
Report an issue: GitHub.