JakeWharton/butterknife · error · IllegalStateException
Multiple listener methods specified on @%s.
Error message
Multiple listener methods specified on @%s.
What it means
@ListenerClass supports two mutually exclusive shapes: exactly one method() entry, or a callbacks() enum (including the default NONE sentinel). If a @ListenerClass declares more than one @ListenerMethod in its method() attribute, the processor cannot decide which listener method to bind and throws this IllegalStateException. This is a compile-time contract violation in the annotation definition.
Source
Thrown at butterknife-compiler/src/main/java/butterknife/compiler/ButterKnifeProcessor.java:1105
if (ids.length == 1) {
if (!required) {
error(element, "ID-free binding must not be annotated with @Optional. (%s.%s)",
enclosingElement.getQualifiedName(), element.getSimpleName());
hasError = true;
}
} else {
error(element, "@%s annotation contains invalid ID %d. (%s.%s)",
annotationClass.getSimpleName(), id, enclosingElement.getQualifiedName(),
element.getSimpleName());
hasError = true;
}
}
}
ListenerMethod method;
ListenerMethod[] methods = listener.method();
if (methods.length > 1) {
throw new IllegalStateException(String.format("Multiple listener methods specified on @%s.",
annotationClass.getSimpleName()));
} else if (methods.length == 1) {
if (listener.callbacks() != ListenerClass.NONE.class) {
throw new IllegalStateException(
String.format("Both method() and callback() defined on @%s.",
annotationClass.getSimpleName()));
}
method = methods[0];
} else {
Method annotationCallback = annotationClass.getDeclaredMethod("callback");
Enum<?> callback = (Enum<?>) annotationCallback.invoke(annotation);
Field callbackField = callback.getDeclaringClass().getField(callback.name());
method = callbackField.getAnnotation(ListenerMethod.class);
if (method == null) {
throw new IllegalStateException(
String.format("No @%s defined on @%s's %s.%s.", ListenerMethod.class.getSimpleName(),
annotationClass.getSimpleName(), callback.getDeclaringClass().getSimpleName(),
callback.name()));View on GitHub (pinned to fcdebedf32)
Solutions
- Keep only one @ListenerMethod in method() and remove the extras
- If multiple callbacks are needed, remove method() and provide a callbacks() enum whose constants each carry @ListenerMethod
Example fix
// before
@ListenerClass(method = {
@ListenerMethod(name = "onClick", parameters = {View.class}),
@ListenerMethod(name = "onLongClick", parameters = {View.class})})
public @interface OnClickOrLong { ... }
// after
@ListenerClass(
callbacks = OnClickOrLong.Callback.class,
... )
public @interface OnClickOrLong {
enum Callback {
@ListenerMethod(name = "onClick", parameters = {View.class}) CLICK,
@ListenerMethod(name = "onLongClick", parameters = {View.class}) LONG_CLICK
}
} Defensive patterns
Strategy: validation
Validate before calling
ListenerClass lc = OnCustomEvent.class.getAnnotation(ListenerClass.class);
if (lc.method().length > 1) {
throw new IllegalStateException("Use callbacks(), not multiple method() entries");
} Prevention
- Remember method() accepts exactly one @ListenerMethod; use callbacks() for multi-callback listeners
- Codereview custom @ListenerClass definitions against this rule
When it happens
Trigger: Declaring @ListenerClass(method = {@ListenerMethod(...), @ListenerMethod(...)}) with two or more entries on a custom listener annotation.
Common situations: Attempting to make one custom annotation bind several callbacks by listing multiple method entries; misunderstanding that multi-callback listeners use the callbacks enum instead.
Related errors
- Both method() and callback() defined on @%s.
- @%s's %s.%s missing @%s annotation.
- @%s annotation must be on a method.
- @%s annotation value() type not int[].
- No @%s defined on @%s's %s.%s.
AI-assisted analysis of JakeWharton/butterknife@fcdebedf32 (2026-08-14).
Data as JSON: /api/errors/8faf286576e5acbd.
Report an issue: GitHub.