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
- Trim the method parameters to at most the callback's parameter count (e.g. 0 or 1 (View) for @OnClick).
- Look up the listener interface ButterKnife wraps for that annotation and copy its exact signature, or use none.
- 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
- Limit listener-method parameters to the wrapped callback's count (usually 0 or 1).
- ButterKnife only forwards actual callback arguments — it never injects positions/ids.
- Use butterknife-compiler for compile-time signature checking.
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
- must have return type of
- Unable to match <class>.<method> method arguments.\n\n Para
- @BindDimen field type must be 'int' or 'float'. (
- @BindDrawable field type must be 'Drawable'. (
- @BindFloat field type must be 'float'. (
AI-assisted analysis of JakeWharton/butterknife@fcdebedf32 (2026-08-14).
Data as JSON: /api/errors/b211648f85f113fd.
Report an issue: GitHub.