{"record":{"id":"6d3ac81b399f5a0f","repo":"JakeWharton/butterknife","slug":"parameter-of-method-was-of-the-wrong-type","errorCode":null,"errorMessage":"Parameter #{} of method '{}' was of the wrong type for parameter #{} of method '{}'. See cause for more info.","messagePattern":"Parameter #(.+?) of method '(.+?)' was of the wrong type for parameter #(.+?) of method '(.+?)'\\. See cause for more info\\.","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"butterknife-runtime/src/main/java/butterknife/internal/Utils.java","lineNumber":120,"sourceCode":"      return cls.cast(view);\n    } catch (ClassCastException e) {\n      String name = getResourceEntryName(view, id);\n      throw new IllegalStateException(\"View '\"\n          + name\n          + \"' with ID \"\n          + id\n          + \" for \"\n          + who\n          + \" was of the wrong type. See cause for more info.\", e);\n    }\n  }\n\n  public static <T> T castParam(Object value, String from, int fromPos, String to, int toPos,\n      Class<T> cls) {\n    try {\n      return cls.cast(value);\n    } catch (ClassCastException e) {\n      throw new IllegalStateException(\"Parameter #\"\n          + (fromPos + 1)\n          + \" of method '\"\n          + from\n          + \"' was of the wrong type for parameter #\"\n          + (toPos + 1)\n          + \" of method '\"\n          + to\n          + \"'. See cause for more info.\", e);\n    }\n  }\n\n  private static String getResourceEntryName(View view, @IdRes int id) {\n    if (view.isInEditMode()) {\n      return \"<unavailable while editing>\";\n    }\n    return view.getContext().getResources().getResourceEntryName(id);\n  }\n","sourceCodeStart":102,"sourceCodeEnd":138,"githubUrl":"https://github.com/JakeWharton/butterknife/blob/fcdebedf3276096db2f51bf6372b849b5a9c75ed/butterknife-runtime/src/main/java/butterknife/internal/Utils.java#L102-L138","documentation":"Thrown by Utils.castParam during listener-method argument wiring when a parameter of an @On* method cannot be cast to the parameter type the framework callback actually supplies. The original ClassCastException is the cause; the message names both methods (from/to) and both parameter positions so the mismatch is pinpointed.","triggerScenarios":"With the reflect binder's argument matching or generated code, a listener parameter whose declared type is narrower than the callback's: e.g. `@OnTextChanged(R.id.q) void onText(String s)` (callback passes CharSequence), or `@OnItemClick void pick(String item)` where the adapter supplies Object — ClassCastException at castParam during bind/registration.","commonSituations":"Writing listener signatures from memory instead of the framework interface (String vs CharSequence is the classic case); custom adapters whose getItem returns Object; AdapterView callbacks delivering a generic type after a library update changed the callback signature.","solutions":["Match the framework callback's parameter types exactly or accept a supertype (CharSequence instead of String, Object instead of a model class).","Cast inside the method body (`((String) s)`) only when you control the producer and know the runtime type.","Copy signatures from the wrapped listener interface docs (TextWatcher, AdapterView.OnItemClickListener, etc.)."],"exampleFix":"// before\n@OnTextChanged(R.id.search) void onSearch(String text) { }\n\n// after\n@OnTextChanged(R.id.search) void onSearch(CharSequence text) { }","handlingStrategy":"type-guard","validationCode":"Class<?>[] cb = {CharSequence.class, int.class, int.class, int.class};\nfor (Class<?> p : method.getParameterTypes()) {\n  boolean ok = false;\n  for (Class<?> c : cb) ok |= c.isAssignableFrom(p);\n  if (!ok) throw new IllegalStateException(p + \" cannot receive any callback param\");\n}","typeGuard":"static boolean canReceive(Class<?> callbackParam, Class<?> methodParam) {\n  return callbackParam.isAssignableFrom(methodParam) || methodParam == callbackParam;\n}","tryCatchPattern":null,"preventionTips":["Write listener signatures from the framework interface, from memory as 'widest type wins' (CharSequence, Object).","Cast to the concrete type inside the method only when the producer is under your control.","Use butterknife-compiler to catch parameter mismatches at build time."],"tags":["butterknife","classcast","listener","parameters","type-mismatch"],"backgroundTag":null,"analyzedSha":"fcdebedf3276096db2f51bf6372b849b5a9c75ed","analyzedAt":"2026-08-14T10:13:55.083Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}