JakeWharton/butterknife · error · IllegalStateException

Unable to match <class>.<method> method arguments.\n\n Para

Error message

Unable to match <class>.<method> method arguments.\n\n  Parameter #N: <type>\n    did not match any listener parameters\n\nMethods may have up to N parameter(s):\n\n  <callbackParameterTypes>\n\nThese may be listed in any order but will be searched for from top to bottom.

What it means

Thrown by ButterKnife's reflection binder when none of an @On* method's parameters can be matched by type to the wrapped listener callback's parameters. ButterKnife builds a map from each method parameter to a compatible callback parameter (searched top to bottom); if any parameter finds no match, binding aborts with a diagnostic listing the method's parameters, the available callback parameters, and the parameter count limit.

Source

Thrown at butterknife-reflect/src/main/java/butterknife/ButterKnife.java:1093

            .append("\n    ");
        if (i < targetIndex) {
          builder.append("matched listener parameter #")
              .append(indexMap[i])
              .append(": ")
              .append(callbackParameterTypes[indexMap[i]].getName());
        } else {
          builder.append("did not match any listener parameters");
        }
      }
      builder.append("\n\nMethods may have up to ")
          .append(callbackParameterLength)
          .append(" parameter(s):\n");
      for (Class<?> callbackParameter : callbackParameterTypes) {
        builder.append("\n  ").append(callbackParameter.getName());
      }
      builder.append(
          "\n\nThese may be listed in any order but will be searched for from top to bottom.");
      throw new IllegalStateException(builder.toString());
    }

    return new ArgumentTransformer() {
      @Override public Object[] transform(Object... arguments) {
        Object[] newArguments = new Object[indexMap.length];
        for (int i = 0; i < indexMap.length; i++) {
          newArguments[i] = arguments[indexMap[i]];
        }
        return newArguments;
      }

      @Override public String toString() {
        StringBuilder builder = new StringBuilder("ArgumentTransformer[");
        for (int i = 0; i < indexMap.length; i++) {
          if (i > 0) {
            builder.append(", ");
          }
          builder.append(i).append(" => ").append(indexMap[i]);

View on GitHub (pinned to fcdebedf32)

Solutions

  1. Read the message: make each method parameter's type assignable from the corresponding callback parameter (e.g. CharSequence not String for @OnTextChanged).
  2. Drop parameters you do not need — ButterKnife allows any subset up to the callback's count.
  3. Prefer butterknife-compiler so mismatches fail at compile time.

Example fix

// before
@OnTextChanged(R.id.query) void onQuery(String text) { }

// after
@OnTextChanged(R.id.query) void onQuery(CharSequence text) { }
Defensive patterns

Strategy: validation

Validate before calling

// Ensure every parameter is assignable from some callback parameter
Class<?>[] cb = {CharSequence.class, int.class, int.class, int.class}; // TextWatcher
outer:
for (Class<?> p : method.getParameterTypes()) {
  for (Class<?> c : cb) {
    if (c.isAssignableFrom(p) || p.isAssignableFrom(c)) continue outer;
  }
  throw new IllegalStateException("No listener parameter matches " + p);
}

Type guard

static boolean paramMatchesCallback(Class<?> param, Class<?>[] callbackParams) {
  for (Class<?> c : callbackParams) {
    if (c.isAssignableFrom(param)) return true; // param can receive c
  }
  return false;
}

Prevention

When it happens

Trigger: ButterKnife.bind(...) via butterknife-reflect where a listener method's parameters are not assignable from the callback's parameter types — e.g. `@OnTextChanged(R.id.field) void text(String s)` while TextWatcher passes (CharSequence, int, int, int), or `@OnItemClick void item(int position)` where the callback supplies an AdapterView and View but no int.

Common situations: Assuming ButterKnife injects arbitrary values (positions, ids, ints) instead of only the actual callback arguments; using String where the callback gives CharSequence; reordering/renaming parameters during refactoring. Compile-time binder reports the equivalent error at build time; the reflect path surfaces it at runtime with this message.

Related errors


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