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
- Read the message: make each method parameter's type assignable from the corresponding callback parameter (e.g. CharSequence not String for @OnTextChanged).
- Drop parameters you do not need — ButterKnife allows any subset up to the callback's count.
- 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
- Use supertypes of callback parameters (CharSequence over String, View over Button).
- Omit parameters you do not need instead of inventing values.
- Read the thrown message: it lists the acceptable callback parameter types verbatim.
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
- must have at most parameter(s).
- Parameter #{} of method '{}' was of the wrong type for param
- @BindView fields must extend from View or be an interface. (
- @BindViews must be a List or array. (
- @BindViews List or array type must extend from View or be an
AI-assisted analysis of JakeWharton/butterknife@fcdebedf32 (2026-08-14).
Data as JSON: /api/errors/cb5d9eefd2474758.
Report an issue: GitHub.