Tencent/tinker · error · UTFDataFormatException
bad second byte
Error message
bad second byte
What it means
Thrown by Mutf8.decode when decoding a 2-byte MUTF-8 sequence whose second byte is not a 0b10xxxxxx continuation. In MUTF-8 (dex string encoding), bytes 0xC0–0xDF lead a 2-byte char and the next byte must be 0x80–0xBF; anything else is malformed.
Source
Thrown at third-party/aosp-dexutils/src/main/java/com/tencent/tinker/android/dex/Mutf8.java:47
/**
* Decodes bytes from {@code in} into {@code out} until a delimiter 0x00 is
* encountered. Returns a new string containing the decoded characters.
*/
public static String decode(ByteInput in, char[] out) throws UTFDataFormatException {
int s = 0;
while (true) {
char a = (char) (in.readByte() & 0xff);
if (a == 0) {
return new String(out, 0, s);
}
out[s] = a;
if (a < '\u0080') {
s++;
} else if ((a & 0xe0) == 0xc0) {
int b = in.readByte() & 0xff;
if ((b & 0xC0) != 0x80) {
throw new UTFDataFormatException("bad second byte");
}
out[s++] = (char) (((a & 0x1F) << 6) | (b & 0x3F));
} else if ((a & 0xf0) == 0xe0) {
int b = in.readByte() & 0xff;
int c = in.readByte() & 0xff;
if (((b & 0xC0) != 0x80) || ((c & 0xC0) != 0x80)) {
throw new UTFDataFormatException("bad second or third byte");
}
out[s++] = (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 1b7ea02c23)
Solutions
- Validate the dex header checksum/signature; if it fails, the string data is corrupt — obtain a clean copy.
- If you produce the dex with custom tooling, encode strings with Mutf8.encode (or a spec-conformant encoder) rather than java.lang.String.getBytes(UTF-8).
- Cross-check with baksmali — if baksmali decodes fine, your reader's offset is wrong, not the data.
Defensive patterns
Strategy: try-catch
Try / catch
try { String s = Mutf8.decode(in, utf16Len); } catch (UTFDataFormatException e) { mark dex as unusable and fall back to a placeholder string with its id logged; never continue parsing mid-string } Prevention
- Treat any MUTF-8 failure as a signal the whole string section is suspect; revalidate the file instead of skipping one string.
- Produce dexes only with spec-conformant encoders (Mutf8.encode, d8).
When it happens
Trigger: Decoding a dex string_id's MUTF-8 data where a 2-byte sequence's continuation byte was corrupted, or where the string bytes were written by a buggy encoder (or a buffer read started one byte into a multi-byte char).
Common situations: Corrupted dex string data from bad patching or partial writes; third-party string obfuscation/encryption tools that mangle MUTF-8; reading a dex buffer with the wrong offset into string_data_item.
Related errors
- bad second or third byte
- bad byte
- Declared length ${expectedLength} doesn't match decoded leng
- Unexpected type: ${type}
- invalid LEB128 sequence
AI-assisted analysis of Tencent/tinker@1b7ea02c23 (2026-08-14).
Data as JSON: /api/errors/b276666bd8f165e0.
Report an issue: GitHub.