microg/GmsCore · error · IllegalArgumentException
No non-synthetic fields were found
Error message
No non-synthetic fields were found
What it means
After skipping synthetic (instrumentation-added, e.g. JaCoCo $jacocoData) fields, ObjectWrapper.unwrap requires exactly one real field to hold the wrapped object. If none remains, it throws IllegalArgumentException('No non-synthetic fields were found').
Source
Thrown at play-services-basement/src/main/java/com/google/android/gms/dynamic/ObjectWrapper.java:68
// 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");
}
}
if (field == null) {
throw new IllegalArgumentException("No non-synthetic fields were found");
}
if (!field.isAccessible()) {
field.setAccessible(true);
try {
return field.get(binder);
} catch (NullPointerException localNullPointerException) {
throw new IllegalArgumentException("Binder object is null.",
localNullPointerException);
} catch (IllegalArgumentException localIllegalArgumentException) {
throw new IllegalArgumentException("remoteBinder is the wrong class.",
localIllegalArgumentException);
} catch (IllegalAccessException localIllegalAccessException) {
throw new IllegalArgumentException("Could not access the field in remoteBinder.",
localIllegalAccessException);
}
} else {
throw new IllegalArgumentException();View on GitHub (pinned to 157c9d86ac)
Solutions
- Exclude com.google.android.gms.** from JaCoCo/proguard/R8 instrumentation and shrinking (keepclassmembers for the wrapper field)
- Ensure the binder is a genuine ObjectWrapper remote binder created by ObjectWrapper.wrap
- Verify no test/instrumentation agent is transforming the class at runtime
- Pass the wrapped object directly if you have it, avoiding the binder round-trip
Example fix
// before
Object v = ObjectWrapper.unwrap(binder); // fails under JaCoCo
// after
if (binder instanceof ObjectWrapper) {
Object v = ObjectWrapper.unwrapTyped(binder, Object.class);
} else {
Object v = binder; // already local
} Defensive patterns
Strategy: try-catch
Validate before calling
IBinder b = wrapper.asBinder();
boolean hasReal = false;
for (Field f : b.getClass().getDeclaredFields()) {
if (!f.isSynthetic() && !f.getName().startsWith("$jacoco")) { hasReal = true; break; }
}
if (!hasReal) { /* reject: only synthetic fields */ } Try / catch
try {
T value = ObjectWrapper.unwrapTyped(wrapper, T.class);
} catch (IllegalArgumentException e) {
// JaCoCo/proguard stripped the field — use local object instead
} Prevention
- Exclude com.google.android.gms.** from JaCoCo instrumentation
- Add proguard keep rules for com.google.android.gms.dynamic.**
- If the wrapped object is local, skip the binder unwrap entirely
When it happens
Trigger: unwrap() called on a binder class whose only declared fields are synthetic — commonly a JaCoCo-instrumented build where $jacocoData is filtered out, an empty mock/proxy subclass, or a wrapper class whose payload field was stripped by proguard/R8.
Common situations: Running code under JaCoCo coverage where the remote binder class got instrumented; obfuscation removing the wrapper's field; mocks standing in for IObjectWrapper in production paths.
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
- Could not access the field in remoteBinder.
- No Creator found for " + tClass.getName()
- No fields were found
- Too many non-synthetic fields were found
- Binder object is null.
AI-assisted analysis of microg/GmsCore@157c9d86ac (2026-09-06).
Data as JSON: /api/errors/3392072860da01c9.
Report an issue: GitHub.