Netflix/Hystrix · error · IllegalStateException
batch method is absent: {}
Error message
batch method is absent: {} What it means
The @HystrixCollapser annotation names a batchMethod, and Javanica looks it up on the same class via getDeclaredMethod(clazz, batchMethod, List.class). If no method with that exact name and a single java.util.List parameter exists (declared on the class, not inherited), an IllegalStateException is thrown. Note it uses getDeclaredMethod, so the batch method must be declared directly on the target class.
Source
Thrown at hystrix-contrib/hystrix-javanica/src/main/java/com/netflix/hystrix/contrib/javanica/aop/aspectj/HystrixCommandAspect.java:205
setFallbackMethod(builder, obj.getClass(), method);
builder = setDefaultProperties(builder, obj.getClass(), joinPoint);
return builder;
}
}
private static class CollapserMetaHolderFactory extends MetaHolderFactory {
@Override
public MetaHolder create(Object proxy, Method collapserMethod, Object obj, Object[] args, final ProceedingJoinPoint joinPoint) {
HystrixCollapser hystrixCollapser = collapserMethod.getAnnotation(HystrixCollapser.class);
if (collapserMethod.getParameterTypes().length > 1 || collapserMethod.getParameterTypes().length == 0) {
throw new IllegalStateException("Collapser method must have one argument: " + collapserMethod);
}
Method batchCommandMethod = getDeclaredMethod(obj.getClass(), hystrixCollapser.batchMethod(), List.class);
if (batchCommandMethod == null)
throw new IllegalStateException("batch method is absent: " + hystrixCollapser.batchMethod());
Class<?> batchReturnType = batchCommandMethod.getReturnType();
Class<?> collapserReturnType = collapserMethod.getReturnType();
boolean observable = collapserReturnType.equals(Observable.class);
if (!collapserMethod.getParameterTypes()[0]
.equals(getFirstGenericParameter(batchCommandMethod.getGenericParameterTypes()[0]))) {
throw new IllegalStateException("required batch method for collapser is absent, wrong generic type: expected "
+ obj.getClass().getCanonicalName() + "." +
hystrixCollapser.batchMethod() + "(java.util.List<" + collapserMethod.getParameterTypes()[0] + ">), but it's " +
getFirstGenericParameter(batchCommandMethod.getGenericParameterTypes()[0]));
}
final Class<?> collapserMethodReturnType = getFirstGenericParameter(
collapserMethod.getGenericReturnType(),
Future.class.isAssignableFrom(collapserReturnType) || Observable.class.isAssignableFrom(collapserReturnType) ? 1 : 0);
Class<?> batchCommandActualReturnType = getFirstGenericParameter(batchCommandMethod.getGenericReturnType());View on GitHub (pinned to 5ce3bc58c3)
Solutions
- Declare a method with the exact batchMethod name on the same class taking exactly one java.util.List parameter.
- Check spelling/case of the batchMethod attribute against the real method name.
- If the batch method lives in a superclass, move or override it on the collapser's class (lookup uses getDeclaredMethod).
Example fix
// before
@HystrixCollapser(batchMethod = "getUserByIds")
public Future<User> getUserById(String id) { ... }
// no matching method, or: public List<User> getUserByIds(Collection<String> ids)
// after
@HystrixCollapser(batchMethod = "getUserByIds")
public Future<User> getUserById(String id) { ... }
@HystrixCommand
public List<User> getUserByIds(List<String> ids) { ... } Defensive patterns
Strategy: validation
Validate before calling
static void assertBatchMethodExists(Class<?> clazz, HystrixCollapser c) {
boolean found = false;
for (Method m : clazz.getDeclaredMethods()) {
if (m.getName().equals(c.batchMethod())
&& m.getParameterTypes().length == 1
&& m.getParameterTypes()[0] == java.util.List.class) { found = true; break; }
}
if (!found) throw new IllegalStateException("batch method missing: " + clazz.getName() + "." + c.batchMethod() + "(List)");
} Try / catch
Startup self-test: invoke each collapser once in a test context inside try/catch (IllegalStateException) and surface the message; treat any 'batch method is absent' as build failure.
Prevention
- Keep collapser method and batch method adjacent in the same class and update batchMethod strings via IDE rename refactoring (it does not rename string references — so prefer constants or tests).
- Reflection-based CI test enumerating all @HystrixCollapser annotations and verifying the named batch method exists with a single List parameter on the declaring class.
When it happens
Trigger: @HystrixCollapser(batchMethod = "foo") where foo does not exist, is misspelled, has a different name, or exists but does not take exactly one List parameter (e.g. takes Collection, varargs, or List plus another arg). Also thrown when the batch method is inherited from a superclass rather than declared on the class.
Common situations: Renaming the batch method without updating batchMethod; batch method defined in an interface or superclass; batch method parameter typed as Collection<String> or ArrayList instead of List.
Related errors
- Collapser method must have one argument: {}
- required batch method for collapser is absent, wrong generic
- batch method must be annotated with HystrixCommand annotatio
- method cannot be annotated with HystrixCommand and HystrixCo
- Return type of batch method must be java.util.List parametri
AI-assisted analysis of Netflix/Hystrix@5ce3bc58c3 (2026-08-14).
Data as JSON: /api/errors/23a0a67642a2b622.
Report an issue: GitHub.