microg/GmsCore · error · IllegalArgumentException

No fields were found

Error message

No fields were found

What it means

ObjectWrapper.unwrap reflects over the underlying binder's class to find the wrapped object's field. It throws IllegalArgumentException('No fields were found') when the binder's class declares zero fields, which means the object passed is not a real ObjectWrapper remote binder.

Source

Thrown at play-services-basement/src/main/java/com/google/android/gms/dynamic/ObjectWrapper.java:46

    public ObjectWrapper(T t) {
        this.t = t;
    }

    @Nullable
    public static Object unwrap(IObjectWrapper obj) {
        if (obj == null) {
            return null;
        }

        if (obj instanceof ObjectWrapper) {
            return ((ObjectWrapper) obj).t;
        }

        IBinder binder = obj.asBinder();
        Field[] fields = binder.getClass().getDeclaredFields();

        if (fields.length < 1) {
            throw new IllegalArgumentException("No fields were found");
        }

        // Ignore synthetic field(s) from JaCoCo or elsewhere
        // https://www.jacoco.org/jacoco/trunk/doc/faq.html

        @Nullable
        Field field = null;

        for (Field currentField : fields) {
            if (currentField.isSynthetic()) {
                continue;
            }

            if (field == null) {
                field = currentField;
            } else {
                throw new IllegalArgumentException("Too many non-synthetic fields were found");
            }

View on GitHub (pinned to 157c9d86ac)

Solutions

  1. Pass only IObjectWrapper instances created via ObjectWrapper.wrap(obj), not mocks or hand-built implementations
  2. Disable proguard minification/obfuscation for com.google.android.gms.dynamic.** (keep class members)
  3. Align play-services-basement versions across all modules
  4. In tests, use ObjectWrapper.wrap(realObject) instead of Mockito.mock(IObjectWrapper.class)

Example fix

// before
IObjectWrapper w = Mockito.mock(IObjectWrapper.class);
MyType t = ObjectWrapper.unwrapTyped(w, MyType.class); // throws
// after
IObjectWrapper w = ObjectWrapper.wrap(new MyTypeImpl());
MyType t = ObjectWrapper.unwrapTyped(w, MyType.class);
Defensive patterns

Strategy: try-catch

Validate before calling

if (wrapper == null) return null;
IBinder b = wrapper.asBinder();
if (b == null || b.getClass().getDeclaredFields().length == 0) return null; // would throw

Type guard

boolean isWrappable(IObjectWrapper w) {
    if (w == null) return false;
    IBinder b = w.asBinder();
    return b != null && b.getClass().getDeclaredFields().length >= 1;
}

Try / catch

try {
    T value = ObjectWrapper.unwrapTyped(wrapper, T.class);
} catch (IllegalArgumentException e) {
    Log.w(TAG, "unwrap failed", e);
    value = null;
}

Prevention

When it happens

Trigger: Calling ObjectWrapper.unwrap() on an IObjectWrapper whose asBinder() class has no declared fields — typically a Mockito-style mock, a lambda/proxy subclass, or an ObjectWrapper created by a different/older library version whose internal layout changed.

Common situations: Unit tests injecting mocked IObjectWrapper instances into production code; proguard/R8 renaming or stripping the field; mixed play-services versions in a multi-module build.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


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