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

  1. Inspect the cause: if InvocationTargetException wraps an NPE/IllegalState from the handler body, fix that exception at its source.
  2. Add ProGuard keep rules (`-keepclassmembers class ** { @butterknife.* <methods>; }`) or switch to butterknife-compiler which needs no reflection.
  3. 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

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


AI-assisted analysis of JakeWharton/butterknife@fcdebedf32 (2026-08-14). Data as JSON: /api/errors/19b02c3c111d1310. Report an issue: GitHub.