JakeWharton/butterknife · error · RuntimeException
Unable to invoke on with arguments
Error message
Unable to invoke on with arguments
What it means
Wrapped in a RuntimeException and rethrown by ButterKnife's reflect binder (tryInvoke) when Method.invoke fails with IllegalAccessException or InvocationTargetException during listener registration/proxy invocation. The message names the method, target, and arguments; the cause holds the underlying failure.
Source
Thrown at butterknife-reflect/src/main/java/butterknife/ButterKnife.java:1135
static void trySet(Field field, Object target, @Nullable Object value) {
try {
field.set(target, value);
} catch (IllegalAccessException e) {
throw new RuntimeException("Unable to assign " + value + " to " + field + " on " + target, e);
}
}
private static Object tryInvoke(Method method, Object target, Object... arguments) {
Throwable cause;
try {
return method.invoke(target, arguments);
} catch (IllegalAccessException e) {
cause = e;
} catch (InvocationTargetException e) {
cause = e;
}
throw new RuntimeException(
"Unable to invoke " + method + " on " + target + " with arguments "
+ Arrays.toString(arguments), cause);
}
private static final Setter<CompoundButton, CompoundButton.OnCheckedChangeListener>
ON_CHECKED_CHANGE = (view, value, index) -> view.setOnCheckedChangeListener(value);
private static final Setter<View, View.OnClickListener> ON_CLICK =
(view, value, index) -> view.setOnClickListener(value);
private static final Setter<TextView, TextView.OnEditorActionListener> ON_EDITOR_ACTION =
(view, value, index) -> view.setOnEditorActionListener(value);
private static final Setter<View, View.OnFocusChangeListener> ON_FOCUS_CHANGE =
(view, value, index) -> view.setOnFocusChangeListener(value);
private static final Setter<AdapterView<?>, AdapterView.OnItemClickListener> ON_ITEM_CLICK =
(view, value, index) -> view.setOnItemClickListener(value);
private static final Setter<AdapterView<?>, AdapterView.OnItemLongClickListener>
ON_ITEM_LONG_CLICK = (view, value, index) -> view.setOnItemLongClickListener(value);
private static final Setter<View, View.OnLongClickListener> ON_LONG_CLICK =
(view, value, index) -> view.setOnLongClickListener(value);View on GitHub (pinned to fcdebedf32)
Solutions
- Inspect the cause: if InvocationTargetException wraps an NPE/IllegalState from the handler body, fix that exception at its source.
- Add ProGuard keep rules (`-keepclassmembers class ** { @butterknife.* <methods>; }`) or switch to butterknife-compiler which needs no reflection.
- Ensure listener methods are non-private, non-static, and not renamed by build tooling.
Example fix
# before (proguard-rules.pro has no keeps, reflect binder)
# after
-keep class **_ViewBinding { *; }
-keepclassmembers class ** {
@butterknife.* <methods>;
@butterknife.* <fields>;
} Defensive patterns
Strategy: try-catch
Validate before calling
int m = method.getModifiers();
if ((m & (Modifier.PRIVATE | Modifier.STATIC)) != 0) {
throw new IllegalStateException(method + " not reflectively invocable");
} Try / catch
try {
ButterKnife.bind(target, source);
} catch (RuntimeException e) {
Throwable c = e.getCause();
if (c instanceof InvocationTargetException && c.getCause() != null) {
throw new RuntimeException("Handler threw: " + c.getCause(), c.getCause());
}
throw e;
} Prevention
- Keep @On* methods non-private and non-static; add ProGuard keeps for them.
- If the cause is InvocationTargetException, the real bug is inside your handler body — debug that.
- Use butterknife-compiler to eliminate reflective invocation entirely.
When it happens
Trigger: ButterKnife.bind(...) via butterknife-reflect when invoking an @OnClick/@On* method fails reflectively: the method became inaccessible (ProGuard renamed/removed it, setAccessible blocked), or the proxy invocation threw a checked exception not declared by the method.
Common situations: Obfuscated release builds where the annotation survives but the method does not; listener callbacks running on a different thread hitting access checks; handler methods whose bodies throw (the InvocationTargetException case) — e.g. an @OnClick that dereferences a null bundled extra. Distinct from the normal case where a listener's own exception propagates: this wrapper means the reflective call itself could not complete.
Related errors
- must have return type of
- must have at most parameter(s).
- Unable to match <class>.<method> method arguments.\n\n Para
- Unable to assign to on
- Unable to invoke {}
AI-assisted analysis of JakeWharton/butterknife@fcdebedf32 (2026-08-14).
Data as JSON: /api/errors/19b02c3c111d1310.
Report an issue: GitHub.