JakeWharton/butterknife · error · IllegalStateException
must have return type of
Error message
must have return type of
What it means
Thrown by ButterKnife's reflection binder when an @On* listener method declares a non-void return type that does not exactly match the expected type of the listener callback (e.g. boolean for OnTouchListener/OnLongClickListener/OnEditorActionListener). ButterKnife supports either void or the listener's own return type so return values propagate correctly; anything else is rejected.
Source
Thrown at butterknife-reflect/src/main/java/butterknife/ButterKnife.java:1003
+ " must not be private or static");
}
if ((modifiers & PUBLIC) == 0) {
object.setAccessible(true);
}
}
/** Returns true when the return value should be propagated. Use a default otherwise. */
private static boolean validateReturnType(Method method, Class<?> expected) {
Class<?> returnType = method.getReturnType();
if (returnType == void.class) {
return false;
}
if (returnType != expected) {
String expectedType = "'" + expected.getName() + "'";
if (expected != void.class) {
expectedType = "'void' or " + expectedType;
}
throw new IllegalStateException(method.getDeclaringClass().getName()
+ "."
+ method.getName()
+ " must have return type of "
+ expectedType);
}
return true;
}
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) {View on GitHub (pinned to fcdebedf32)
Solutions
- Make the listener method return `void` when the return value is unused (ButterKnife supplies the default).
- Or return exactly the listener callback's type: boolean for @OnLongClick/@OnTouch/@OnEditorActionListener, void for clicks/checked/text changes.
- Match the parameter list too, then switch to butterknife-compiler for compile-time validation.
Example fix
// before
@OnLongClick(R.id.item) String onLongClick() { return "ok"; }
// after
@OnLongClick(R.id.item) boolean onLongClick() { return true; } Defensive patterns
Strategy: validation
Validate before calling
// Mirror of validateReturnType for an @OnLongClick method
Method m = ...;
Class<?> rt = m.getReturnType();
if (rt != void.class && rt != boolean.class) {
throw new IllegalStateException(m + " must return void or boolean");
} Prevention
- Return void for listeners whose return value you ignore.
- Copy the exact callback signature from the wrapped listener interface (e.g. OnLongClickListener returns boolean).
- Use butterknife-compiler so return types are checked at build time.
When it happens
Trigger: ButterKnife.bind(...) via butterknife-reflect where a method annotated @OnClick/@OnTouch/etc. returns a type that is neither void nor the callback's return type — e.g. `@OnTouch(R.id.area) boolean onTouch() {...}` on a listener whose callback returns void, or an @OnLongClick method returning String.
Common situations: Copying a listener implementation with the wrong signature, changing a handler to return a status object, or an @OnEditorActionListener method returning void while the framework expects boolean (silent behavior change) or vice versa. Compiler binder checks the same rule at build time; reflect defers it to bind time.
Related errors
- must have at most parameter(s).
- @BindDimen field type must be 'int' or 'float'. (
- @BindDrawable field type must be 'Drawable'. (
- @BindFloat field type must be 'float'. (
- @BindFont style must be NORMAL, BOLD, ITALIC, or BOLD_ITALIC
AI-assisted analysis of JakeWharton/butterknife@fcdebedf32 (2026-08-14).
Data as JSON: /api/errors/21e7e9afa2ce49c3.
Report an issue: GitHub.