{"record":{"id":"c06ac88c178107f9","repo":"JakeWharton/butterknife","slug":"unable-to-assign-to-on","errorCode":null,"errorMessage":"Unable to assign  to  on ","messagePattern":"Unable to assign  to  on ","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"butterknife-reflect/src/main/java/butterknife/ButterKnife.java","lineNumber":1122,"sourceCode":"\n      @Override public String toString() {\n        StringBuilder builder = new StringBuilder(\"ArgumentTransformer[\");\n        for (int i = 0; i < indexMap.length; i++) {\n          if (i > 0) {\n            builder.append(\", \");\n          }\n          builder.append(i).append(\" => \").append(indexMap[i]);\n        }\n        return builder.append(']').toString();\n      }\n    };\n  }\n\n  static void trySet(Field field, Object target, @Nullable Object value) {\n    try {\n      field.set(target, value);\n    } catch (IllegalAccessException e) {\n      throw new RuntimeException(\"Unable to assign \" + value + \" to \" + field + \" on \" + target, e);\n    }\n  }\n\n  private static Object tryInvoke(Method method, Object target, Object... arguments) {\n    Throwable cause;\n    try {\n      return method.invoke(target, arguments);\n    } catch (IllegalAccessException e) {\n      cause = e;\n    } catch (InvocationTargetException e) {\n      cause = e;\n    }\n    throw new RuntimeException(\n        \"Unable to invoke \" + method + \" on \" + target + \" with arguments \"\n            + Arrays.toString(arguments), cause);\n  }\n\n  private static final Setter<CompoundButton, CompoundButton.OnCheckedChangeListener>","sourceCodeStart":1104,"sourceCodeEnd":1140,"githubUrl":"https://github.com/JakeWharton/butterknife/blob/fcdebedf3276096db2f51bf6372b849b5a9c75ed/butterknife-reflect/src/main/java/butterknife/ButterKnife.java#L1104-L1140","documentation":"Wrapped in a RuntimeException and rethrown by ButterKnife's reflect binder (trySet) when Field.set fails with IllegalAccessException while assigning a bound resource/view value to an annotated field. The message names the value, field, and target; the cause carries the original exception.","triggerScenarios":"ButterKnife.bind(...) via butterknife-reflect when field.set throws IllegalAccessException — typically a final field, a field in a module/SDK class where accessibility was suppressed, or a race where another component (e.g. an obfuscator or security manager) blocks reflective writes even after setAccessible(true).","commonSituations":"ProGuard/R8 stripping or renaming annotated fields while keeping the @BindView metadata; binding into classes loaded by a different classloader in plugin architectures; JVM unit tests (not Robolectric) where android.jar stubs throw; fields made final by a code generator. The compiler-generated binder does not use reflection, so this is specific to butterknife-reflect.","solutions":["Check the cause chain: remove `final` from the annotated field and ensure it is not private/static (see validateMember rules).","Add ProGuard keep rules for annotated fields and the target classes when using butterknife-reflect.","Replace butterknife-reflect with butterknife-compiler so field assignment is direct code, not reflection.","If running plain JVM tests without android.jar implementations, use Robolectric or an instrumentation test."],"exampleFix":"// before\nfinal @BindView(R.id.title) TextView title; // reflective write may fail\n\n// after\n@BindView(R.id.title) TextView title;","handlingStrategy":"try-catch","validationCode":"int m = field.getModifiers();\nif (Modifier.isFinal(m) || Modifier.isPrivate(m) || Modifier.isStatic(m)) {\n  throw new IllegalStateException(field + \" cannot be reflectively assigned\");\n}","typeGuard":null,"tryCatchPattern":"try {\n  ButterKnife.bind(target, source);\n} catch (RuntimeException e) {\n  if (e.getCause() instanceof IllegalAccessException) {\n    // fix field modifiers / keep rules, then report\n    throw new IllegalStateException(\"Binding blocked: \" + e.getCause(), e);\n  }\n  throw e;\n}","preventionTips":["Never mark bound fields final/private/static.","Keep ProGuard rules for annotated fields when using butterknife-reflect.","Prefer butterknife-compiler: direct assignment, no reflection."],"tags":["butterknife","reflection","illegal-access","proguard","field-assignment"],"backgroundTag":null,"analyzedSha":"fcdebedf3276096db2f51bf6372b849b5a9c75ed","analyzedAt":"2026-08-14T10:13:55.083Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}