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.
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)
Solutions
- Ensure the same serializer (writeUTF/readUTF or writeLongUTF/readLongUTF pair) is used on both sides.
- Verify the buffer was fully populated before decoding (available() >= utflen + lengthPrefixSize).
- 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
- Always pair writeUTF with readUTF (and writeLongUTF with readLongUTF).
- Keep the same TypeSerializer version on writer and reader sides.
- Treat UTFDataFormatException as data corruption and isolate the affected record/partition.
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
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- malformed input around byte {count}
- malformed input around byte {count-1}
- Error reconstructing URI
- Failed to deserialize an element from the source. If you are
- Reached the end of the collection. This could be caused by i
AI-assisted analysis of apache/flink@2f3c205e92 (2026-08-14).
Data as JSON: /api/errors/ad8e62beaa19fac4.
Report an issue: GitHub.