microg/GmsCore · error · ReadException

Expected object header. Got 0x" +…

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.

Solutions

  1. Verify the Parcel was written by SafeParcelable serialization and read from position 0
  2. Ensure writer and reader classes/versions match
  3. Check that no fields were consumed before readStart()
  4. 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

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


AI-assisted analysis of microg/GmsCore@157c9d86ac (2026-09-06). Data as JSON: /api/errors/e01a5e42e8c928fb. Report an issue: GitHub.

Appendix: 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)