google/ExoPlayer · error · IllegalStateException
Top bit not zero: {result}
Error message
Top bit not zero: {result} What it means
ParsableByteArray.readUnsignedIntToInt() reads the next four bytes as a signed int and throws IllegalStateException if the result is negative, i.e. if the most significant bit (top bit) of the four bytes is set. The method's contract is to narrow a 32-bit unsigned value into a Java int; a set top bit means the byte stream's value actually needs 32 unsigned bits (>= 2^31), which does not fit, so the data is either malformed or being read at the wrong position with the wrong endianness.
Source
Thrown at library/common/src/main/java/com/google/android/exoplayer2/util/ParsableByteArray.java:403
* @return The parsed value.
*/
public int readSynchSafeInt() {
int b1 = readUnsignedByte();
int b2 = readUnsignedByte();
int b3 = readUnsignedByte();
int b4 = readUnsignedByte();
return (b1 << 21) | (b2 << 14) | (b3 << 7) | b4;
}
/**
* Reads the next four bytes as an unsigned integer into an integer, if the top bit is a zero.
*
* @throws IllegalStateException Thrown if the top bit of the input data is set.
*/
public int readUnsignedIntToInt() {
int result = readInt();
if (result < 0) {
throw new IllegalStateException("Top bit not zero: " + result);
}
return result;
}
/**
* Reads the next four bytes as a little endian unsigned integer into an integer, if the top bit
* is a zero.
*
* @throws IllegalStateException Thrown if the top bit of the input data is set.
*/
public int readLittleEndianUnsignedIntToInt() {
int result = readLittleEndianInt();
if (result < 0) {
throw new IllegalStateException("Top bit not zero: " + result);
}
return result;
}
View on GitHub (pinned to dd430f7053)
Solutions
- Validate position/limit alignment before reading the field — usually the real bug is an earlier misread offset
- If the field legitimately needs 32 bits, switch to readUnsignedInt() (returns long) and range-check it yourself
- Use the correct endianness variant: readLittleEndianUnsignedIntToInt for little-endian formats
- Wrap container parsing per-item so one malformed field skips the section (with a parser exception) instead of crashing playback
Example fix
// before int size = parsableByteArray.readUnsignedIntToInt(); // top bit set on 4GB-ish payloads // after long sizeLong = parsableByteArray.readUnsignedInt(); checkState(sizeLong <= Integer.MAX_VALUE, "Size %s exceeds int range", sizeLong); int size = (int) sizeLong;
Defensive patterns
Strategy: try-catch
Validate before calling
if (data.limit() - data.getPosition() < 4) { /* not enough bytes: fail before reading */ } Try / catch
try { v = p.readUnsignedIntToInt(); } catch (IllegalStateException e) { throw new ParserException("Malformed 32-bit field", e); } Prevention
- Use the unsigned-to-long reader (readUnsignedInt) when the field may use all 32 bits
- Confirm field endianness against the container spec before parsing
- Feed parsers through ExtractorOutput error paths so one bad field fails the item, not playback
When it happens
Trigger: Parsing a container/protocol field documented as '31-bit max' where the encoder wrote a full 32-bit value; reading at a wrong offset so a large size/timestamp field lands in the int slot; interpreting big-endian data as big-endian here is correct but data was written little-endian (use readLittleEndianUnsignedIntToInt instead); corrupted or truncated downloads feeding garbage into the parser.
Common situations: Custom or evolving MP4/EBML/section parsers (DVB, PES, HLS tags) where a length field occasionally exceeds Integer.MAX_VALUE on 4K/long recordings; partial file reads making subsequent fields misaligned; firmware/encoder writing nonstandard 32-bit values into fields spec'd at 31 bits.
Related errors
- Cannot read frame at position ${lastDecodePosition}
- Invalid index {index}, size is {size}
- Invalid UTF-8 sequence first byte: {value}
- Invalid UTF-8 sequence continuation byte: {value}
- Unsupported charset: %s
AI-assisted analysis of google/ExoPlayer@dd430f7053 (2026-08-14).
Data as JSON: /api/errors/bd8f085fc257e189.
Report an issue: GitHub.