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

  1. 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
  2. Re-encode the input string via Mutf8.encode / utf8Bytes before decoding
  3. 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

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


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)