Netflix/Hystrix · error · IllegalStateException
method cannot be annotated with HystrixCommand and HystrixCo
Error message
method cannot be annotated with HystrixCommand and HystrixCollapser annotations at the same time
What it means
Hystrix Javanica's AspectJ aspect intercepts methods annotated with either @HystrixCommand or @HystrixCollapser, but a single method must not carry both. The two annotations build completely different command pipelines (a plain wrapped command vs. a request-batching collapser delegating to a batch method), so the aspect refuses to guess and throws IllegalStateException at the first intercepted call.
Source
Thrown at hystrix-contrib/hystrix-javanica/src/main/java/com/netflix/hystrix/contrib/javanica/aop/aspectj/HystrixCommandAspect.java:91
.put(HystrixPointcutType.COLLAPSER, new CollapserMetaHolderFactory())
.build();
}
@Pointcut("@annotation(com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand)")
public void hystrixCommandAnnotationPointcut() {
}
@Pointcut("@annotation(com.netflix.hystrix.contrib.javanica.annotation.HystrixCollapser)")
public void hystrixCollapserAnnotationPointcut() {
}
@Around("hystrixCommandAnnotationPointcut() || hystrixCollapserAnnotationPointcut()")
public Object methodsAnnotatedWithHystrixCommand(final ProceedingJoinPoint joinPoint) throws Throwable {
Method method = getMethodFromTarget(joinPoint);
Validate.notNull(method, "failed to get method from joinPoint: %s", joinPoint);
if (method.isAnnotationPresent(HystrixCommand.class) && method.isAnnotationPresent(HystrixCollapser.class)) {
throw new IllegalStateException("method cannot be annotated with HystrixCommand and HystrixCollapser " +
"annotations at the same time");
}
MetaHolderFactory metaHolderFactory = META_HOLDER_FACTORY_MAP.get(HystrixPointcutType.of(method));
MetaHolder metaHolder = metaHolderFactory.create(joinPoint);
HystrixInvokable invokable = HystrixCommandFactory.getInstance().create(metaHolder);
ExecutionType executionType = metaHolder.isCollapserAnnotationPresent() ?
metaHolder.getCollapserExecutionType() : metaHolder.getExecutionType();
Object result;
try {
if (!metaHolder.isObservable()) {
result = CommandExecutor.execute(invokable, executionType, metaHolder);
} else {
result = executeObservable(invokable, executionType, metaHolder);
}
} catch (HystrixBadRequestException e) {
throw e.getCause() != null ? e.getCause() : e;
} catch (HystrixRuntimeException e) {View on GitHub (pinned to 5ce3bc58c3)
Solutions
- Remove one of the two annotations from the method — they are mutually exclusive by design.
- If you want collapsing, keep only @HystrixCollapser on the single-argument method and move the @HystrixCommand onto the batchMethod it references.
- If you want a plain command, delete @HystrixCollapser and keep @HystrixCommand.
Example fix
// before
@HystrixCommand
@HystrixCollapser(batchMethod = "getUserByIds")
public Future<User> getUserById(String id) { ... }
// 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 assertSingleAnnotation(Method m) {
boolean cmd = m.isAnnotationPresent(com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand.class);
boolean col = m.isAnnotationPresent(com.netflix.hystrix.contrib.javanica.annotation.HystrixCollapser.class);
if (cmd && col) throw new IllegalArgumentException(m + " has both @HystrixCommand and @HystrixCollapser");
} Try / catch
catch (IllegalStateException e) when message starts with 'method cannot be annotated' -> treat as a startup/config defect: fail the deploy, log the method name, fix the annotations. Do not swallow.
Prevention
- Run an ArchUnit or reflection-based startup check that every @HystrixCommand/@HystrixCollapser method has exactly one of the two annotations.
- Code-review rule: @HystrixCollapser belongs on single-arg request methods; @HystrixCommand on the batch method — never both on one method.
When it happens
Trigger: Any method annotated with both @HystrixCommand and @HystrixCollapser, invoked through the aspect (Spring bean woven by HystrixCommandAspect). The check runs in methodsAnnotatedWithHystrixCommand before any MetaHolderFactory work.
Common situations: Copy-pasting a @HystrixCollapser method from an example onto an existing @HystrixCommand method; IDE auto-import picking the wrong annotation and stacking them during refactoring.
Related errors
- batch method must be annotated with HystrixCommand annotatio
- Collapser method must have one argument: {}
- batch method is absent: {}
- 'https://github.com/Netflix/Hystrix/issues/1458' - no valid
- AsyncResult is just a stub and cannot be used as complete im
AI-assisted analysis of Netflix/Hystrix@5ce3bc58c3 (2026-08-14).
Data as JSON: /api/errors/5e0061f775f23dbe.
Report an issue: GitHub.