microg/GmsCore · error · ReadException
Expected object header. Got 0x" + Integer.toHexString(header
Error message
Expected object header. Got 0x" + Integer.toHexString(header)
What it means
SafeParcelReader.readObjectHeader() (used by readStart) verifies that the header it reads is an object-start marker (SAFE_PARCEL_OBJECT_MAGIC) and throws ReadException 'Expected object header. Got 0x...' when the field id in the header does not match. It also validates the size/end position against the Parcel bounds. This indicates the stream is misaligned or was not written by SafeParcelable serialization.
Source
Thrown at play-services-basement/src/main/java/com/google/android/gms/common/internal/safeparcel/SafeParcelReader.java:62
}
private static void readExpectedSize(Parcel parcel, int header, int expectedSize) {
int i = readSize(parcel, header);
if (i != expectedSize)
throw new ReadException("Expected size " + expectedSize + " got " + i + " (0x" + Integer.toHexString(i) + ")", parcel);
}
@Deprecated
public static int readStart(Parcel parcel) {
return readObjectHeader(parcel);
}
public static int readObjectHeader(Parcel parcel) {
int header = readHeader(parcel);
int size = readSize(parcel, header);
int start = parcel.dataPosition();
if (getFieldId(header) != SafeParcelable.SAFE_PARCEL_OBJECT_MAGIC)
throw new ReadException("Expected object header. Got 0x" + Integer.toHexString(header), parcel);
int end = start + size;
if ((end < start) || (end > parcel.dataSize()))
throw new ReadException("Size read is invalid start=" + start + " end=" + end, parcel);
return end;
}
public static int readInt(Parcel parcel, int header) {
readExpectedSize(parcel, header, 4);
return parcel.readInt();
}
public static byte readByte(Parcel parcel, int header) {
readExpectedSize(parcel, header, 4);
return (byte) parcel.readInt();
}
public static short readShort(Parcel parcel, int header) {
readExpectedSize(parcel, header, 4);View on GitHub (pinned to 157c9d86ac)
Solutions
- Verify the Parcel was written by SafeParcelable serialization and read from position 0
- Ensure writer and reader classes/versions match
- Check that no fields were consumed before readStart()
- Catch ReadException and fall back to alternative parsing
Example fix
// before
int end = SafeParcelReader.readStart(parcel); // parcel position misaligned
// after
try {
int end = SafeParcelReader.readStart(parcel);
} catch (SafeParcelReader.ReadException e) {
throw new IllegalArgumentException("Not a SafeParcelable parcel", e);
} Defensive patterns
Strategy: try-catch
Validate before calling
// ensure parcel.dataPosition() == 0 and data written by SafeParcelable before readStart()
Try / catch
try { int end = SafeParcelReader.readStart(parcel); } catch (SafeParcelReader.ReadException e) { handleMalformedHeader(e); } Prevention
- Read from dataPosition 0; don't consume fields before readStart
- Match reader/writer versions exactly
- Wrap unmarshalling in ReadException handling
When it happens
Trigger: Calling SafeParcelReader.readStart(parcel) on a Parcel whose next object is not a SafeParcel object header, e.g. a plain Bundle, wrong dataPosition, or extra/missing fields causing misalignment.
Common situations: Reading a Parcel from a different starting offset; parsing Parcels written by non-SafeParcelable code; version skew between writer and reader field counts.
Understand the failure class
Background: "cannot parse invalid wire-format data", "cannot unmarshal", "failed unmarshalling": protobuf unmarshal errors explained — this error's family across 10 libraries.
Related errors
- Expected size " + expectedSize + " got " + i + " (0x" + Inte
- Size read is invalid start=" + start + " end=" + end
- null reference
- Could not read from parcel file descriptor
- ParcelableKeyValue.key must be > 0
AI-assisted analysis of microg/GmsCore@157c9d86ac (2026-09-06).
Data as JSON: /api/errors/e01a5e42e8c928fb.
Report an issue: GitHub.