{"record":{"id":"8faf286576e5acbd","repo":"JakeWharton/butterknife","slug":"multiple-listener-methods-specified-on-s","errorCode":null,"errorMessage":"Multiple listener methods specified on @%s.","messagePattern":"Multiple listener methods specified on @(.+?)\\.","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"butterknife-compiler/src/main/java/butterknife/compiler/ButterKnifeProcessor.java","lineNumber":1105,"sourceCode":"        if (ids.length == 1) {\n          if (!required) {\n            error(element, \"ID-free binding must not be annotated with @Optional. (%s.%s)\",\n                enclosingElement.getQualifiedName(), element.getSimpleName());\n            hasError = true;\n          }\n        } else {\n          error(element, \"@%s annotation contains invalid ID %d. (%s.%s)\",\n              annotationClass.getSimpleName(), id, enclosingElement.getQualifiedName(),\n              element.getSimpleName());\n          hasError = true;\n        }\n      }\n    }\n\n    ListenerMethod method;\n    ListenerMethod[] methods = listener.method();\n    if (methods.length > 1) {\n      throw new IllegalStateException(String.format(\"Multiple listener methods specified on @%s.\",\n          annotationClass.getSimpleName()));\n    } else if (methods.length == 1) {\n      if (listener.callbacks() != ListenerClass.NONE.class) {\n        throw new IllegalStateException(\n            String.format(\"Both method() and callback() defined on @%s.\",\n                annotationClass.getSimpleName()));\n      }\n      method = methods[0];\n    } else {\n      Method annotationCallback = annotationClass.getDeclaredMethod(\"callback\");\n      Enum<?> callback = (Enum<?>) annotationCallback.invoke(annotation);\n      Field callbackField = callback.getDeclaringClass().getField(callback.name());\n      method = callbackField.getAnnotation(ListenerMethod.class);\n      if (method == null) {\n        throw new IllegalStateException(\n            String.format(\"No @%s defined on @%s's %s.%s.\", ListenerMethod.class.getSimpleName(),\n                annotationClass.getSimpleName(), callback.getDeclaringClass().getSimpleName(),\n                callback.name()));","sourceCodeStart":1087,"sourceCodeEnd":1123,"githubUrl":"https://github.com/JakeWharton/butterknife/blob/fcdebedf3276096db2f51bf6372b849b5a9c75ed/butterknife-compiler/src/main/java/butterknife/compiler/ButterKnifeProcessor.java#L1087-L1123","documentation":"@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.","triggerScenarios":"Declaring @ListenerClass(method = {@ListenerMethod(...), @ListenerMethod(...)}) with two or more entries on a custom listener annotation.","commonSituations":"Attempting to make one custom annotation bind several callbacks by listing multiple method entries; misunderstanding that multi-callback listeners use the callbacks enum instead.","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"],"exampleFix":"// before\n@ListenerClass(method = {\n    @ListenerMethod(name = \"onClick\", parameters = {View.class}),\n    @ListenerMethod(name = \"onLongClick\", parameters = {View.class})})\npublic @interface OnClickOrLong { ... }\n\n// after\n@ListenerClass(\n    callbacks = OnClickOrLong.Callback.class,\n    ... )\npublic @interface OnClickOrLong {\n  enum Callback {\n    @ListenerMethod(name = \"onClick\", parameters = {View.class}) CLICK,\n    @ListenerMethod(name = \"onLongClick\", parameters = {View.class}) LONG_CLICK\n  }\n}","handlingStrategy":"validation","validationCode":"ListenerClass lc = OnCustomEvent.class.getAnnotation(ListenerClass.class);\nif (lc.method().length > 1) {\n  throw new IllegalStateException(\"Use callbacks(), not multiple method() entries\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Remember method() accepts exactly one @ListenerMethod; use callbacks() for multi-callback listeners","Codereview custom @ListenerClass definitions against this rule"],"tags":["butterknife","annotation-processing","listener","contract"],"backgroundTag":null,"analyzedSha":"fcdebedf3276096db2f51bf6372b849b5a9c75ed","analyzedAt":"2026-08-14T10:13:55.083Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}