greenrobot/EventBus · error · EventBusException
${methodName} is a illegal @Subscribe method: must be public
Error message
${methodName} is a illegal @Subscribe method: must be public, non-static, and non-abstract What it means
Thrown during method verification in SubscriberMethodFinder when strictMethodVerification is enabled and a method carries @Subscribe but its modifiers fail the check (modifiers & Modifier.PUBLIC) == 0 or (modifiers & MODIFIERS_IGNORE) != 0, i.e. the method is not public, or is static/abstract (MODIFIERS_IGNORE covers static, abstract, and synthetic/bridge). EventBus invokes handlers via Method.invoke on the public method; non-public, static, or abstract methods cannot serve as instance handlers.
Source
Thrown at EventBus/src/org/greenrobot/eventbus/SubscriberMethodFinder.java:191
Class<?>[] parameterTypes = method.getParameterTypes();
if (parameterTypes.length == 1) {
Subscribe subscribeAnnotation = method.getAnnotation(Subscribe.class);
if (subscribeAnnotation != null) {
Class<?> eventType = parameterTypes[0];
if (findState.checkAdd(method, eventType)) {
ThreadMode threadMode = subscribeAnnotation.threadMode();
findState.subscriberMethods.add(new SubscriberMethod(method, eventType, threadMode,
subscribeAnnotation.priority(), subscribeAnnotation.sticky()));
}
}
} else if (strictMethodVerification && method.isAnnotationPresent(Subscribe.class)) {
String methodName = method.getDeclaringClass().getName() + "." + method.getName();
throw new EventBusException("@Subscribe method " + methodName +
"must have exactly 1 parameter but has " + parameterTypes.length);
}
} else if (strictMethodVerification && method.isAnnotationPresent(Subscribe.class)) {
String methodName = method.getDeclaringClass().getName() + "." + method.getName();
throw new EventBusException(methodName +
" is a illegal @Subscribe method: must be public, non-static, and non-abstract");
}
}
}
static void clearCaches() {
METHOD_CACHE.clear();
}
static class FindState {
final List<SubscriberMethod> subscriberMethods = new ArrayList<>();
final Map<Class, Object> anyMethodByEventType = new HashMap<>();
final Map<String, Class> subscriberClassByMethodKey = new HashMap<>();
final StringBuilder methodKeyBuilder = new StringBuilder(128);
Class<?> subscriberClass;
Class<?> clazz;
boolean skipSuperClasses;View on GitHub (pinned to 0194926b3b)
Solutions
- Make the handler method public and non-static: public void onEvent(MessageEvent event)
- For abstract contracts, remove @Subscribe from the abstract method and annotate each concrete public override instead
- For static helpers, move the annotation to a public instance method that delegates
Example fix
// before
@Subscribe
protected void onMessage(MessageEvent event) { ... } // not public -> throws
// after
@Subscribe
public void onMessage(MessageEvent event) { ... } Defensive patterns
Strategy: validation
Validate before calling
for (Method m : subscriberClass.getDeclaredMethods()) {
Subscribe ann = m.getAnnotation(Subscribe.class);
if (ann != null) {
int mod = m.getModifiers();
if (!Modifier.isPublic(mod) || Modifier.isStatic(mod) || Modifier.isAbstract(mod)) {
throw new IllegalStateException("@Subscribe method " + m + " must be public, non-static, non-abstract");
}
}
} Prevention
- Keep handlers public instance methods; in Java avoid package-private 'encapsulation' on handlers
- Don't annotate abstract base methods; annotate the concrete overrides
When it happens
Trigger: Annotating a private, protected, or package-private handler; annotating a static method (often a util 'handler'); annotating an abstract method in a base class that concrete subclasses implement; registering the class triggers the scan and throws.
Common situations: Kotlin functions default to public so this mostly hits Java code with visibility reductions after refactoring; abstract base-class handler contracts; IDE auto-generating static helper overloads; deliberate encapsulation (private handlers) by teams unaware EventBus requires public.
Related errors
- @Subscribe method ${methodName}must have exactly 1 parameter
- Event may not be null
- Only the currently handled event may be aborted
- Subscriber ${subscriberClass} and its super classes have no
- It looks like you are using EventBus on Android, make sure t
AI-assisted analysis of greenrobot/EventBus@0194926b3b (2026-08-14).
Data as JSON: /api/errors/ec8a01bf563adc8f.
Report an issue: GitHub.