pxb1988/dex2jar · error · UTFDataFormatException
bad byte
Error message
bad byte
What it means
Thrown by Mutf8.decode when a lead byte is outside the valid MUTF-8 ranges: it is >= 0xF0 (including 4-byte UTF-8 sequences, which Modified UTF-8 does not support) or a byte with pattern 10xx xxxx appearing as a lead byte.
Solutions
- Ensure producers encode with Modified UTF-8 (e.g. DataOutputStream.writeUTF semantics), where supplementary chars are 6-byte surrogate pairs, not 4-byte UTF-8
- Re-encode the input string via Mutf8.encode / utf8Bytes before decoding
- Catch UTFDataFormatException and log the offending offset; treat the DEX as invalid
Example fix
// before byte[] raw = standardUtf8String.getBytes(StandardCharsets.UTF_8); // after byte[] raw = Mutf8.encode(s); // MUTF-8: surrogates as two 3-byte sequences
Defensive patterns
Strategy: validation
Validate before calling
for (byte x : bytes) { int a = x & 0xff; if (a >= 0xF0) return false; } // reject 4-byte UTF-8 leads before decode Type guard
boolean isMutf8Compatible(byte[] bytes) { return java.util.Arrays.stream(bytes).noneMatch(b -> (b & 0xff) >= 0xF0); } Try / catch
try { return Mutf8.decode(buf, pos); } catch (UTFDataFormatException e) { log.error("non-MUTF-8 byte at " + pos[0]); return new String(rawFallback, StandardCharsets.UTF_8); } Prevention
- Encode with Mutf8.encode / DataOutputStream.writeUTF, never raw UTF-8 bytes
- Remember MUTF-8 has no 4-byte sequences: supplementary chars must go through surrogate pairs
- Reject or transcode external UTF-8 data before feeding it into MUTF-8 decoders
When it happens
Trigger: Decoding bytes containing standard UTF-8 4-byte sequences (e.g. emoji, supplementary characters encoded as surrogate pairs outside Java) or continuation bytes where a lead byte was expected.
Common situations: Strings encoded with standard UTF-8 instead of Modified UTF-8 (surrogate-pair 4-byte encodings), corrupted input, misaligned buffer offsets.
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 second or third byte
- bad utf-8 byte %02x at offset %08x
- String more than 65535 UTF bytes long
- Odex unsupported.
AI-assisted analysis of pxb1988/dex2jar@b5bda4fb49 (2026-09-08).
Data as JSON: /api/errors/a9ef2971af56f801.
Report an issue: GitHub.
Appendix: source
Thrown at dex-reader/src/main/java/com/googlecode/d2j/util/Mutf8.java:59
}
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;
} else if (ch <= 2047) {
result += 2;
} else {
result += 3;View on GitHub (pinned to b5bda4fb49)