{"record":{"id":"50d882da937dbd03","repo":"microg/GmsCore","slug":"too-many-non-synthetic-fields-were-found","errorCode":null,"errorMessage":"Too many non-synthetic fields were found","messagePattern":"Too many non-synthetic fields were found","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"play-services-basement/src/main/java/com/google/android/gms/dynamic/ObjectWrapper.java","lineNumber":63,"sourceCode":"        if (fields.length < 1) {\n            throw new IllegalArgumentException(\"No fields were found\");\n        }\n\n        // Ignore synthetic field(s) from JaCoCo or elsewhere\n        // https://www.jacoco.org/jacoco/trunk/doc/faq.html\n\n        @Nullable\n        Field field = null;\n\n        for (Field currentField : fields) {\n            if (currentField.isSynthetic()) {\n                continue;\n            }\n\n            if (field == null) {\n                field = currentField;\n            } else {\n                throw new IllegalArgumentException(\"Too many non-synthetic fields were found\");\n            }\n        }\n\n        if (field == null) {\n            throw new IllegalArgumentException(\"No non-synthetic fields were found\");\n        }\n\n        if (!field.isAccessible()) {\n            field.setAccessible(true);\n            try {\n                return field.get(binder);\n            } catch (NullPointerException localNullPointerException) {\n                throw new IllegalArgumentException(\"Binder object is null.\",\n                        localNullPointerException);\n            } catch (IllegalArgumentException localIllegalArgumentException) {\n                throw new IllegalArgumentException(\"remoteBinder is the wrong class.\",\n                        localIllegalArgumentException);\n            } catch (IllegalAccessException localIllegalAccessException) {","sourceCodeStart":45,"sourceCodeEnd":81,"githubUrl":"https://github.com/microg/GmsCore/blob/157c9d86ac46c195a86c2f15ab55c84036223f95/play-services-basement/src/main/java/com/google/android/gms/dynamic/ObjectWrapper.java#L45-L81","documentation":"ObjectWrapper.unwrap expects the remote binder class to expose exactly one non-synthetic field (the wrapped object). If reflection finds two or more non-synthetic fields it cannot determine which one holds the payload and throws IllegalArgumentException('Too many non-synthetic fields were found').","triggerScenarios":"unwrap() called on a binder whose class has multiple real (non-synthetic) fields — i.e., the class is not the single-field ObjectWrapper$* remote wrapper, e.g., some other Binder subclass, a mock with multiple fields, or a different library version's wrapper with a changed layout.","commonSituations":"Receiving an IObjectWrapper from an app using a different Google Play services version whose wrapper gained fields; passing arbitrary Binder objects; test doubles with extra fields.","solutions":["Only unwrap IObjectWrapper instances produced by ObjectWrapper.wrap in the same library version","Align play-services-basement versions across producer and consumer","Keep the wrapper class single-field: exclude com.google.android.gms.dynamic.** from transformations that add fields (e.g., JaCoCo-like instrumentation, DI frameworks)","Re-wrap the object locally instead of unwrapping a foreign binder"],"exampleFix":"// before\nObject value = ObjectWrapper.unwrap(foreignBinder);\n// after\nif (foreignBinder instanceof MyConcreteType) {\n    Object value = ((MyConcreteType) foreignBinder).getValue();\n} else {\n    Object value = ObjectWrapper.unwrapTyped(ObjectWrapper.wrap(foreignBinder), Object.class);\n}","handlingStrategy":"try-catch","validationCode":"IBinder b = wrapper.asBinder();\nint real = 0;\nfor (Field f : b.getClass().getDeclaredFields()) {\n    if (!f.isSynthetic() && !f.getName().startsWith(\"$\")) real++;\n}\nif (real != 1) { /* reject: wrong wrapper class */ }","typeGuard":null,"tryCatchPattern":"try {\n    T value = ObjectWrapper.unwrapTyped(wrapper, T.class);\n} catch (IllegalArgumentException e) {\n    // wrapper layout mismatch — treat as absent / re-wrap locally\n}","preventionTips":["Don't subclass or modify the gms ObjectWrapper/binder classes","Align library versions between the code that wraps and the code that unwraps","Avoid passing arbitrary Binder objects where an IObjectWrapper is expected"],"tags":["android","binder","reflection","version-compat"],"backgroundTag":"type-mismatch","analyzedSha":"157c9d86ac46c195a86c2f15ab55c84036223f95","analyzedAt":"2026-09-06T17:27:33.892Z","contentChangedAt":"2026-09-06T17:27:33.892Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}