JakeWharton/butterknife · error · RuntimeException

Unable to invoke {}

Error message

Unable to invoke {}

What it means

Thrown by the generated-binding path in ButterKnife.bind when constructing the target class's generated ViewBinding class fails reflectively with IllegalAccessException or InstantiationException (constructor.newInstance). This means the binding class was found but could not be instantiated/accessed — not that the @OnClick handler itself threw (InvocationTargetException is unwrapped separately, rethrowing its cause).

Source

Thrown at butterknife/src/main/java/butterknife/ButterKnife.java:172

   *
   * @param target Target class for view binding.
   * @param source View root on which IDs will be looked up.
   */
  @NonNull @UiThread
  public static Unbinder bind(@NonNull Object target, @NonNull View source) {
    Class<?> targetClass = target.getClass();
    if (debug) Log.d(TAG, "Looking up binding for " + targetClass.getName());
    Constructor<? extends Unbinder> constructor = findBindingConstructorForClass(targetClass);

    if (constructor == null) {
      return Unbinder.EMPTY;
    }

    //noinspection TryWithIdenticalCatches Resolves to API 19+ only type.
    try {
      return constructor.newInstance(target, source);
    } catch (IllegalAccessException e) {
      throw new RuntimeException("Unable to invoke " + constructor, e);
    } catch (InstantiationException e) {
      throw new RuntimeException("Unable to invoke " + constructor, e);
    } catch (InvocationTargetException e) {
      Throwable cause = e.getCause();
      if (cause instanceof RuntimeException) {
        throw (RuntimeException) cause;
      }
      if (cause instanceof Error) {
        throw (Error) cause;
      }
      throw new RuntimeException("Unable to create binding instance.", cause);
    }
  }

  @Nullable @CheckResult @UiThread
  private static Constructor<? extends Unbinder> findBindingConstructorForClass(Class<?> cls) {
    Constructor<? extends Unbinder> bindingCtor = BINDINGS.get(cls);
    if (bindingCtor != null || BINDINGS.containsKey(cls)) {

View on GitHub (pinned to fcdebedf32)

Solutions

  1. Add keep rules: `-keep class **_ViewBinding { <init>(...); }` plus keep the annotated members, or use the shipped butterknife proguard rules (`-keep class **_ViewBinding*` guidance in the README).
  2. Clean and rebuild (./gradlew clean assembleDebug) to eliminate stale generated classes on the classpath.
  3. Verify butterknife-compiler matches the butterknife runtime version in dependencies; mismatched versions generate incompatible binding classes.
  4. If it persists, check the cause chain — InstantiationException points to an abstract/interface binding class surviving from an old build, so delete old build/ artifacts.

Example fix

# before: proguard-rules.pro missing butterknife keeps (release crash)
# after
-keep class **_ViewBinding { <init>(...); }
-keepclasseswithmembernames class * { @butterknife.* <fields>; }
-keepclasseswithmembernames class * { @butterknife.* <methods>; }
Defensive patterns

Strategy: try-catch

Validate before calling

// Sanity check before relying on codegen in release builds
try {
  Class.forName(targetClass.getName() + "_ViewBinding");
} catch (ClassNotFoundException e) {
  throw new IllegalStateException("Binding class missing — check butterknife-compiler/keeps", e);
}

Try / catch

try {
  unbinder = ButterKnife.bind(target, source);
} catch (RuntimeException e) {
  Throwable c = e.getCause();
  if (c instanceof IllegalAccessException || c instanceof InstantiationException) {
    // obfuscation/stale-classpath issue: report keep-rule/build problem
    CrashReporter.log("ButterKnife codegen broken: " + c);
  }
  throw e;
}

Prevention

When it happens

Trigger: ButterKnife.bind(activity/view/fragment) where the generated FooViewBinding class exists but its (target, source) constructor is not accessible or the class is abstract/instantiation-blocked — typically ProGuard/R8 renaming or stripping the binding class's constructor after the lookup step, or a stale/duplicated binding class on the classpath.

Common situations: Release builds with obfuscation and missing keep rules for *ViewBinding classes; incremental/instant-run classpath skew where an old binding class without the two-arg constructor is packaged; compiling with butterknife but running against a dex that kept only part of it; binding an inner class whose generated outer reference confuses the constructor lookup.

Related errors


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