pxb1988/dex2jar · error · UTFDataFormatException
bad second or third byte
Error message
bad second or third byte
What it means
Thrown by Mutf8.decode when a lead byte indicated a 3-byte sequence (0xE0-0xEF) but either the second or third continuation byte is missing its 10xx xxxx pattern. The byte stream is not valid Modified UTF-8.
Solutions
- Verify the decode start offset is the byte after the ULEB128 length in string_data
- Re-obtain the DEX file; corruption is likely
- Catch UTFDataFormatException and skip/report the bad string index instead of failing the whole file
Example fix
null
Defensive patterns
Strategy: try-catch
Validate before calling
if ((b & 0xC0) != 0x80 || (c & 0xC0) != 0x80) return false; // pre-check continuation bytes for 3-byte sequences
Type guard
boolean isContinuation(int b) { return (b & 0xC0) == 0x80; } Try / catch
try { return Mutf8.decode(buf, pos); } catch (UTFDataFormatException e) { throw new DexException("invalid string data at offset " + pos[0], e); } Prevention
- Verify buffer alignment before decoding 3-byte sequences
- Check DEX file integrity (checksum) before parsing
- Fail fast on the first bad string rather than proceeding with a drifted position
When it happens
Trigger: Decoding a DEX string where the 3-byte sequence bytes are corrupted, or the buffer position is misaligned so continuation bytes land on unrelated data.
Common situations: Corrupted DEX files, incorrect offset computation into string_data, mixed non-MUTF-8 encoders writing strings into DEX-like blobs.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- bad second byte
- bad utf-8 byte %02x at offset %08x
- bad byte
- bad payload offset for
- String more than 65535 UTF bytes long
AI-assisted analysis of pxb1988/dex2jar@b5bda4fb49 (2026-09-08).
Data as JSON: /api/errors/354066dfcdc8c670.
Report an issue: GitHub.
Appendix: source
Thrown at dex-reader/src/main/java/com/googlecode/d2j/util/Mutf8.java:55
while (true) {
char a = (char) (in.get() & 0xff);
if (a == 0) {
return sb.toString();
}
if (a < '\u0080') {
sb.append(a);
} else if ((a & 0xe0) == 0xc0) {
int b = in.get() & 0xff;
if ((b & 0xC0) != 0x80) {
throw new UTFDataFormatException("bad second byte");
}
sb.append((char) (((a & 0x1F) << 6) | (b & 0x3F)));
} else if ((a & 0xf0) == 0xe0) {
int b = in.get() & 0xff;
int c = in.get() & 0xff;
if (((b & 0xC0) != 0x80) || ((c & 0xC0) != 0x80)) {
throw new UTFDataFormatException("bad second or third byte");
}
sb.append((char) (((a & 0x0F) << 12) | ((b & 0x3F) << 6) | (c & 0x3F)));
} else {
throw new UTFDataFormatException("bad byte");
}
}
}
/**
* Returns the number of bytes the modified UTF8 representation of 's' would take.
*/
private static long countBytes(String s, boolean shortLength) throws UTFDataFormatException {
long result = 0;
final int length = s.length();
for (int i = 0; i < length; ++i) {
char ch = s.charAt(i);
if (ch != 0 && ch <= 127) { // U+0000 uses two bytes.
++result;View on GitHub (pinned to b5bda4fb49)