JakeWharton/butterknife · error · RuntimeException

Unable to find binding constructor for {}

Error message

Unable to find binding constructor for {}

What it means

ButterKnife loaded the generated class Foo_ViewBinding via reflection, but Class.getConstructor(Foo.class, View.class) threw NoSuchMethodException — the generated class exists yet does not expose the expected (TargetType, View) constructor. This is a structural mismatch between the butterknife runtime's expectations and the actually generated code, most commonly caused by mixing incompatible versions of the butterknife-compiler (annotation processor) and the butterknife runtime library.

Source

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

      if (debug) Log.d(TAG, "HIT: Cached in binding map.");
      return bindingCtor;
    }
    String clsName = cls.getName();
    if (clsName.startsWith("android.") || clsName.startsWith("java.")
        || clsName.startsWith("androidx.")) {
      if (debug) Log.d(TAG, "MISS: Reached framework class. Abandoning search.");
      return null;
    }
    try {
      Class<?> bindingClass = cls.getClassLoader().loadClass(clsName + "_ViewBinding");
      //noinspection unchecked
      bindingCtor = (Constructor<? extends Unbinder>) bindingClass.getConstructor(cls, View.class);
      if (debug) Log.d(TAG, "HIT: Loaded binding class and constructor.");
    } catch (ClassNotFoundException e) {
      if (debug) Log.d(TAG, "Not found. Trying superclass " + cls.getSuperclass().getName());
      bindingCtor = findBindingConstructorForClass(cls.getSuperclass());
    } catch (NoSuchMethodException e) {
      throw new RuntimeException("Unable to find binding constructor for " + clsName, e);
    }
    BINDINGS.put(cls, bindingCtor);
    return bindingCtor;
  }
}

View on GitHub (pinned to fcdebedf32)

Solutions

  1. Pin butterknife and butterknife-compiler (and butterknife-gradle-plugin if used) to the exact same version in build.gradle, then clean build.
  2. Run ./gradlew app:dependencies --configuration releaseRuntimeClasspath (and debug) to find a transitive ButterKnife version overriding yours; force alignment with a resolutionStrategy or BOM.
  3. Add the official ProGuard keep rules (-keep class **_ViewBinding { <init>(...); }) so R8 does not strip or alter the generated constructor.
  4. If mismatch persists, inspect app/build/generated/source/apt(或kapt)/.../Foo_ViewBinding.java to see the actual constructor signature and confirm which processor version generated it.

Example fix

// before: version skew produces Foo_ViewBinding without (Foo, View) ctor
// java.lang.RuntimeException: Unable to find binding constructor for com.example.Foo
implementation 'com.jakewharton:butterknife:10.2.3'
annotationProcessor 'com.jakewharton:butterknife-compiler:9.0.0' // stale!

// after: aligned versions + clean build
implementation 'com.jakewharton:butterknife:10.2.3'
annotationProcessor 'com.jakewharton:butterknife-compiler:10.2.3'
// then: ./gradlew clean assembleDebug
Defensive patterns

Strategy: validation

Validate before calling

// Before bind, confirm the generated class has the exact (Target, View) constructor
public static boolean hasValidBindingConstructor(Class<?> targetClass) {
  String name = targetClass.getName();
  if (name.startsWith("android.") || name.startsWith("java.") || name.startsWith("androidx.")) {
    return true; // framework classes: bind() returns Unbinder.EMPTY, no error
  }
  try {
    Class<?> bindingClass = targetClass.getClassLoader().loadClass(name + "_ViewBinding");
    bindingClass.getConstructor(targetClass, View.class);
    return true;
  } catch (NoSuchMethodException e) {
    return false; // version-skewed or altered generated code
  } catch (ClassNotFoundException e) {
    return true; // no generated class: bind() falls back to superclass/EMPTY
  }
}

Try / catch

try {
  unbinder = ButterKnife.bind(this);
} catch (RuntimeException e) {
  if (e.getMessage() != null && e.getMessage().startsWith("Unable to find binding constructor")) {
    // structural mismatch: generated class exists but ctor signature differs ->
    // almost always butterknife compiler/runtime version skew
    throw new IllegalStateException("ButterKnife version mismatch: align butterknife and butterknife-compiler", e);
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling any ButterKnife.bind(...) overload on a class Foo for which Foo_ViewBinding is on the classpath but its constructor signature is not exactly (Foo, View) — e.g. generated by a different (older/newer) ButterKnife version whose constructor takes (Foo, View, Unbinder) or uses a different parameter list, or the generated class was modified/obfuscated so the constructor was renamed or its parameter types changed.

Common situations: Upgrading the butterknife runtime without upgrading butterknife-compiler (or vice versa); transitive dependency resolution silently pulling a mismatched butterknife version (check with gradlew dependencies); ProGuard/R8 obfuscating or removing the constructor signature while keeping the class; stale generated sources after migrating between APT and KAPT.

Related errors


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