{"record":{"id":"a359732fa9ebde27","repo":"microg/GmsCore","slug":"remotebinder-is-the-wrong-class","errorCode":null,"errorMessage":"remoteBinder is the wrong class.","messagePattern":"remoteBinder is the wrong class\\.","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"play-services-basement/src/main/java/com/google/android/gms/dynamic/ObjectWrapper.java","lineNumber":79,"sourceCode":"                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) {\n                throw new IllegalArgumentException(\"Could not access the field in remoteBinder.\",\n                        localIllegalAccessException);\n            }\n        } else {\n            throw new IllegalArgumentException();\n        }\n    }\n\n    @Nullable\n    public static <T> T unwrapTyped(IObjectWrapper obj, Class<T> clazz) {\n        try {\n            return clazz.cast(unwrap(obj));\n        } catch (ClassCastException e) {\n            return null;\n        }\n    }","sourceCodeStart":61,"sourceCodeEnd":97,"githubUrl":"https://github.com/microg/GmsCore/blob/157c9d86ac46c195a86c2f15ab55c84036223f95/play-services-basement/src/main/java/com/google/android/gms/dynamic/ObjectWrapper.java#L61-L97","documentation":"During ObjectWrapper.unwrap, field.get(binder) threw an IllegalArgumentException, rethrown as 'remoteBinder is the wrong class.' The single field's value does not match what the caller expects — i.e., the object stored in the wrapper is not of the expected type for the requested unwrap.","triggerScenarios":"unwrapTyped(w, T.class) where the wrapper actually holds an instance of a different class than T (or the field value's class isn't assignable); cross-version wrapper layout change making the reflective field return a different object.","commonSituations":"Mixed play-services versions between producer and consumer; caller assuming a specific wrapped type that the producer never put there; misconfigured binder transaction returning the wrong remote object.","solutions":["Verify the type passed to unwrapTyped matches what the producer actually wrapped","Align play-services versions on both sides of the binder transaction","Catch IllegalArgumentException and fall back or re-wrap locally","If you control the producer, wrap the exact expected type: ObjectWrapper.wrap(expectedInstance)"],"exampleFix":"// before\nFoo foo = ObjectWrapper.unwrapTyped(w, Foo.class);\n// after\nFoo foo;\ntry {\n    foo = ObjectWrapper.unwrapTyped(w, Foo.class);\n} catch (IllegalArgumentException e) {\n    Log.w(TAG, \"Wrapped object not a Foo\", e);\n    foo = null;\n}","handlingStrategy":"try-catch","validationCode":"// confirm the concrete type before unwrapping\nObject raw = null;\ntry { raw = ObjectWrapper.unwrap(wrapper); } catch (IllegalArgumentException ignored) {}\nif (!(raw instanceof ExpectedType)) { /* wrong class — bail out */ }","typeGuard":null,"tryCatchPattern":"try {\n    T value = ObjectWrapper.unwrapTyped(wrapper, T.class);\n} catch (IllegalArgumentException e) {\n    Log.w(TAG, \"Wrapped object is not \" + T.class.getName(), e);\n    value = null;\n}","preventionTips":["Match the wrapped type between producer and consumer","Keep play-services versions aligned on both sides of the transaction","Wrap exactly the type the consumer will request"],"tags":["android","binder","reflection","type-mismatch"],"backgroundTag":"type-mismatch","analyzedSha":"157c9d86ac46c195a86c2f15ab55c84036223f95","analyzedAt":"2026-09-06T17:27:33.892Z","contentChangedAt":"2026-09-06T17:27:33.892Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}