apache/flink · error · UTFDataFormatException

malformed input: partial character at end

Error message

malformed input: partial character at end

What it means

Thrown while decoding a modified-UTF-8 string in readString (called by readUTF/readLongUTF). A two-byte sequence (lead byte 110xxxxx, cases 12/13) was started but advancing count by 2 overshoots the declared utflen, meaning the declared byte length was too short to hold the trailing character. This signals truncated or corrupted serialized string data.

Solutions

  1. Ensure the same serializer (writeUTF/readUTF or writeLongUTF/readLongUTF pair) is used on both sides.
  2. Verify the buffer was fully populated before decoding (available() >= utflen + lengthPrefixSize).
  3. If data is untrusted or persisted across versions, wrap readUTF in try/catch UTFDataFormatException and treat as schema/state corruption.

Example fix

// before
String s = input.readUTF();

// after
try {
    String s = input.readUTF();
} catch (UTFDataFormatException e) {
    throw new IOException("Corrupted serialized string: " + e.getMessage(), e);
}
Defensive patterns

Strategy: try-catch

Validate before calling

int declared = input.available();
// readUTF reads an unsigned short length prefix, then that many bytes
if (declared < 2) {
    throw new EOFException("Not enough bytes for UTF length prefix");
}

Try / catch

try {
    String s = input.readUTF();
} catch (UTFDataFormatException e) {
    // corrupted/truncated serialized string: surface as state/schema corruption
    throw new IOException("Corrupted UTF string: " + e.getMessage(), e);
}

Prevention

When it happens

Trigger: readUTF() or readLongUTF() on a buffer whose UTF length prefix declares fewer bytes than the multi-byte character at that position requires; e.g. utflen ends mid-character after a 0xC0-0xDF lead byte.

Common situations: Serializer mismatch between the writer and reader; truncated checkpoint/state/network data; a byte buffer that was sliced before the full string was written; hand-crafted byte arrays that don't follow Java modified UTF-8.

Understand the failure class

Related errors


AI-assisted analysis of apache/flink@2f3c205e92 (2026-08-14). Data as JSON: /api/errors/ad8e62beaa19fac4. Report an issue: GitHub.

Appendix: source

Thrown at flink-core/src/main/java/org/apache/flink/core/memory/DataInputDeserializer.java:307

            switch (c >> 4) {
                case 0:
                case 1:
                case 2:
                case 3:
                case 4:
                case 5:
                case 6:
                case 7:
                    /* 0xxxxxxx */
                    count++;
                    chararr[chararrCount++] = (char) c;
                    break;
                case 12:
                case 13:
                    /* 110x xxxx 10xx xxxx */
                    count += 2;
                    if (count > utflen) {
                        throw new UTFDataFormatException(
                                "malformed input: partial character at end");
                    }
                    char2 = (int) bytearr[count - 1];
                    if ((char2 & 0xC0) != 0x80) {
                        throw new UTFDataFormatException("malformed input around byte " + count);
                    }
                    chararr[chararrCount++] = (char) (((c & 0x1F) << 6) | (char2 & 0x3F));
                    break;
                case 14:
                    /* 1110 xxxx 10xx xxxx 10xx xxxx */
                    count += 3;
                    if (count > utflen) {
                        throw new UTFDataFormatException(
                                "malformed input: partial character at end");
                    }
                    char2 = (int) bytearr[count - 2];
                    char3 = (int) bytearr[count - 1];
                    if (((char2 & 0xC0) != 0x80) || ((char3 & 0xC0) != 0x80)) {

View on GitHub (pinned to 2f3c205e92)