JakeWharton/butterknife · error · IllegalStateException

must have at most parameter(s).

Error message

 must have at most  parameter(s).

What it means

Thrown by ButterKnife's reflection binder (createArgumentTransformer) when an @On* listener method declares more parameters than the framework callback it wraps provides. ButterKnife can forward at most as many arguments as the real listener passes (it matches them by type, in any order), so a longer parameter list cannot be satisfied.

Source

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

  }

  private static boolean isRequired(Method method) {
    return method.getAnnotation(Optional.class) == null;
  }

  private static ArgumentTransformer createArgumentTransformer(Method method,
      Class<?>[] callbackParameterTypes) {
    Class<?>[] targetParameterTypes = method.getParameterTypes();

    int targetParameterLength = targetParameterTypes.length;
    if (targetParameterLength == 0) {
      // Special case the common case of no arguments.
      return ArgumentTransformer.EMPTY;
    }

    int callbackParameterLength = callbackParameterTypes.length;
    if (targetParameterLength > callbackParameterLength) {
      throw new IllegalStateException(method.getDeclaringClass().getName()
          + "."
          + method.getName()
          + " must have at most "
          + callbackParameterLength
          + " parameter(s).");
    }

    if (Arrays.equals(targetParameterTypes, callbackParameterTypes)) {
      // Special case the common case of exact argument match.
      return ArgumentTransformer.IDENTITY;
    }

    boolean[] callbackIndexUsed = new boolean[callbackParameterLength];
    final int[] indexMap = new int[targetParameterLength];
    nextTarget: for (int targetIndex = 0; targetIndex < targetParameterLength; targetIndex++) {
      Class<?> targetParameterType = targetParameterTypes[targetIndex];
      for (int callbackIndex = 0; callbackIndex < callbackParameterLength; callbackIndex++) {
        if (callbackIndexUsed[callbackIndex]) {

View on GitHub (pinned to fcdebedf32)

Solutions

  1. Trim the method parameters to at most the callback's parameter count (e.g. 0 or 1 (View) for @OnClick).
  2. Look up the listener interface ButterKnife wraps for that annotation and copy its exact signature, or use none.
  3. Move to butterknife-compiler for a compile-time error.

Example fix

// before
@OnClick(R.id.buy) void buy(View v, int position) { }

// after
@OnClick(R.id.buy) void buy(View v) { }
Defensive patterns

Strategy: validation

Validate before calling

// e.g. @OnClick supplies 1 callback parameter (View)
if (method.getParameterTypes().length > 1) {
  throw new IllegalStateException(method
      + " must have at most 1 parameter(s).");
}

Prevention

When it happens

Trigger: ButterKnife.bind(...) via butterknife-reflect where e.g. `@OnClick(R.id.button) void click(View v, int position)` (2 params > OnClickListener's 1 param) or an @OnCheckedChanged method taking (CompoundButton, boolean, int).

Common situations: Copying a method signature from an AdapterView listener (which has more params) onto a plain click handler, or adding extra context parameters (position, tag) that the developer assumed ButterKnife would inject. The compiler path reports this at build time; reflect throws during bind.

Related errors


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