oracle/graal · error · IllegalArgumentException
malformed input around byte %d
Error message
malformed input around byte %d
What it means
While decoding a 2-byte UTF-8 sequence, BinaryInput checks that the continuation byte has the 10xxxxxx pattern ((c2 & 0xC0) == 0x80). A violation throws IllegalArgumentException('malformed input around byte N') with the 1-based position of the bad byte. This is strict decoder validation copied from DataInputStream-style modified UTF-8 handling.
Source
Thrown at compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/truffle/BinaryInput.java:293
case 3:
case 4:
case 5:
case 6:
case 7:
/* 0xxxxxxx */
byteCount++;
tempEncodingCharBuffer[charCount++] = (char) c1;
break;
case 12:
case 13:
/* 110x xxxx 10xx xxxx */
byteCount += 2;
if (byteCount > len) {
throw new IllegalArgumentException("Partial character at end");
}
c2 = tempEncodingByteBuffer[byteCount - 1];
if ((c2 & 0xC0) != 0x80) {
throw new IllegalArgumentException("malformed input around byte " + byteCount);
}
tempEncodingCharBuffer[charCount++] = (char) (((c1 & 0x1F) << 6) | (c2 & 0x3F));
break;
case 14:
/* 1110 xxxx 10xx xxxx 10xx xxxx */
byteCount += 3;
if (byteCount > len) {
throw new IllegalArgumentException("malformed input: partial character at end");
}
c2 = tempEncodingByteBuffer[byteCount - 2];
c3 = tempEncodingByteBuffer[byteCount - 1];
if (((c2 & 0xC0) != 0x80) || ((c3 & 0xC0) != 0x80)) {
throw new IllegalArgumentException("malformed input around byte " + (byteCount - 1));
}
tempEncodingCharBuffer[charCount++] = (char) (((c1 & 0x0F) << 12) | ((c2 & 0x3F) << 6) | (c3 & 0x3F));
break;
default:
/* 10xx xxxx, 1111 xxxx */View on GitHub (pinned to a66e9ccd1d)
Solutions
- Ensure the string was written by BinaryOutput.writeUTF (modified UTF-8, no plain 4-byte UTF-8 sequences).
- Check stream alignment: verify the preceding reads consumed exactly the bytes they declared (tags, lengths).
- Regenerate the marshalled data with matching producer/consumer versions.
- Avoid hand-constructing the binary format; always use BinaryOutput/BinaryInput pairs.
Defensive patterns
Strategy: validation
Try / catch
try {
String s = in.readUTF();
} catch (IllegalArgumentException e) {
if (e.getMessage() != null && e.getMessage().startsWith("malformed input around byte")) {
// treat record as corrupt: reset stream position, skip or re-transfer
}
} Prevention
- Never hand-encode the wire format; always pair BinaryOutput with BinaryInput
- Check stream alignment after every tagged read
- Round-trip test new payload types before deploying
When it happens
Trigger: readUTF encountering a lead byte 110xxxxx followed by a byte that is not a continuation byte (e.g. ASCII byte or another lead byte) inside the string payload.
Common situations: Bytes were produced by a different encoder (standard UTF-8 with surrogate pairs vs modified UTF-8), memory corruption on the native side, or stream misalignment where readUTF starts at the wrong offset after a previous malformed record.
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
- Partial character at end
- malformed input: partial character at end
- String too long to encode, %s bytes
- Unknown tag %d
- Len must be non negative but was %d
AI-assisted analysis of oracle/graal@a66e9ccd1d (2026-08-14).
Data as JSON: /api/errors/8cbdcb8200537fdb.
Report an issue: GitHub.