pxb1988/dex2jar · error · UTFDataFormatException
bad second byte
Error message
bad second byte
What it means
Thrown by Mutf8.decode when decoding Modified UTF-8: a lead byte indicated a 2-byte sequence (0xC0-0xDF), but the next byte read from the ByteBuffer is not a continuation byte (top bits not 10). The input byte stream is not valid Modified UTF-8, so decoding aborts with UTFDataFormatException.
Solutions
- Verify the string offset is correct: re-parse string_ids_off and ensure the decoder starts at the ULEB128 length prefix, not inside the data
- Check the DEX file is not truncated or corrupted; re-obtain or rebuild it with dx/d8
- Wrap decode in try-catch for UTFDataFormatException and treat the file as invalid rather than crashing
Example fix
// before
String s = Mutf8.decode(buffer, new int[1]); // crashes on corrupt data
// after
int[] pos = new int[1];
try {
String s = Mutf8.decode(buffer, pos);
} catch (UTFDataFormatException e) {
throw new IllegalStateException("corrupt DEX string at " + pos[0], e);
} Defensive patterns
Strategy: validation
Validate before calling
static boolean looksLikeMutf8(java.nio.ByteBuffer in, int start) {
for (int i = start; i < in.limit(); i++) {
int a = in.get(i) & 0xff;
if (a >= 0xF0) return false;
if ((a & 0xE0) == 0xC0 || (a & 0xF0) == 0xE0) {
if (i + 1 >= in.limit() || ((in.get(i + 1) & 0xC0) != 0x80)) return false;
i += 1;
}
}
return true;
} Type guard
boolean isValidMutf8Lead(int a) { return (a & 0x80) == 0 || (a & 0xE0) == 0xC0 || (a & 0xF0) == 0xE0; } Try / catch
try { String s = Mutf8.decode(buf, pos); } catch (UTFDataFormatException e) { log.warn("bad MUTF-8 at " + pos[0]); return null; } Prevention
- Always decode starting at the correct string_data offset (after the ULEB128 length)
- Validate DEX checksum/signature before parsing strings
- Treat decode failures as file corruption, not a library bug
When it happens
Trigger: Decoding a DEX string_data item (or other MUTF-8 blob) whose second byte of a 2-byte sequence is corrupted, misaligned, or the decoder is pointed at the wrong offset.
Common situations: Corrupted or hand-edited DEX files, wrong string offsets after incorrect parsing of string_ids/data offsets, truncated buffers where read position drifts into non-UTF data.
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 or third 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/9130e6dbe468e377.
Report an issue: GitHub.
Appendix: source
Thrown at dex-reader/src/main/java/com/googlecode/d2j/util/Mutf8.java:48
}
/**
* Decodes bytes from {@code in} into {@code sb} until a delimiter 0x00 is encountered. Returns a new string
* containing the decoded characters.
*/
public static String decode(ByteBuffer in, StringBuilder sb) throws UTFDataFormatException {
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.
*/View on GitHub (pinned to b5bda4fb49)