Netflix/Hystrix · error · IllegalStateException
Sub type at nesting level %d of %s is expected to be generic
Error message
Sub type at nesting level %d of %s is expected to be generic
What it means
Thrown by getFirstGenericParameter while walking generic types for a @HystrixCollapser pair: at the requested nesting depth the Type is not a ParameterizedType. Practically this means a raw type was used where a parameterized one is required — most commonly a batch method declared with a raw List (no <T>) or an unparameterized Future/Observable return.
Source
Thrown at hystrix-contrib/hystrix-javanica/src/main/java/com/netflix/hystrix/contrib/javanica/aop/aspectj/HystrixCommandAspect.java:313
}
}
private static Method getAjcMethodFromTarget(JoinPoint joinPoint) {
return getAjcMethodAroundAdvice(joinPoint.getTarget().getClass(), (MethodSignature) joinPoint.getSignature());
}
private static Class<?> getFirstGenericParameter(Type type) {
return getFirstGenericParameter(type, 1);
}
private static Class<?> getFirstGenericParameter(final Type type, final int nestedDepth) {
int cDepth = 0;
Type tType = type;
for (int cDept = 0; cDept < nestedDepth; cDept++) {
if (!(tType instanceof ParameterizedType))
throw new IllegalStateException(String.format("Sub type at nesting level %d of %s is expected to be generic", cDepth, type));
tType = ((ParameterizedType) tType).getActualTypeArguments()[cDept];
}
if (tType instanceof ParameterizedType)
return (Class<?>) ((ParameterizedType) tType).getRawType();
else if (tType instanceof Class)
return (Class<?>) tType;
throw new UnsupportedOperationException("Unsupported type " + tType);
}
private static MetaHolder.Builder setDefaultProperties(MetaHolder.Builder builder, Class<?> declaringClass, final ProceedingJoinPoint joinPoint) {
Optional<DefaultProperties> defaultPropertiesOpt = AopUtils.getAnnotation(joinPoint, DefaultProperties.class);
builder.defaultGroupKey(declaringClass.getSimpleName());
if (defaultPropertiesOpt.isPresent()) {
DefaultProperties defaultProperties = defaultPropertiesOpt.get();
builder.defaultProperties(defaultProperties);
if (StringUtils.isNotBlank(defaultProperties.groupKey())) {View on GitHub (pinned to 5ce3bc58c3)
Solutions
- Parameterize the batch method: public List<User> getUserByIds(List<String> ids) instead of raw List.
- Parameterize the collapser's return type: Future<User>, not raw Future.
- Treat raw-type compiler warnings on collapser/batch methods as errors in your build.
Example fix
// before
@HystrixCommand
public List getUserByIds(List ids) { ... }
// after
@HystrixCommand
public List<User> getUserByIds(List<String> ids) { ... } Defensive patterns
Strategy: validation
Validate before calling
static void assertParameterizedTypes(Method collapser, Method batch) {
if (!(batch.getGenericParameterTypes()[0] instanceof java.lang.reflect.ParameterizedType))
throw new IllegalStateException(batch + " uses raw List — parameterize it");
java.lang.reflect.Type rt = collapser.getGenericReturnType();
if (rt instanceof Class && collapser.getReturnType() == java.util.concurrent.Future.class)
throw new IllegalStateException(collapser + " returns raw Future — parameterize it");
} Try / catch
Catch IllegalStateException during collapser wiring tests; message 'expected to be generic' (nesting level always prints 0 due to a display bug) → fix the raw type declaration; rethrow otherwise.
Prevention
- Enable -Xlint:rawtypes and treat raw-type warnings on collapser/batch methods as build errors.
- Reflection-based CI test asserting all List/Future/Observable declarations in collapser pairs are parameterized.
When it happens
Trigger: Batch method signature public List getUserByIds(List ids) (raw types, e.g. ported pre-generics code); collapser returning raw Future; any place Javanica must read the element type of List/Future/Observable but the declaration omitted type arguments. The 'cDepth' in the message is always 0 (a known cosmetic bug — the loop variable cDept is never printed), which can mislead debugging.
Common situations: Migrating legacy Java 1.4-style service methods into collapsers; IDE raw-type warnings ignored; decompiled or generated code dropping generic signatures.
Related errors
- required batch method for collapser is absent, wrong generic
- Return type of batch method must be java.util.List parametri
- Unsupported type {}
- Collapser method must have one argument: {}
- batch method is absent: {}
AI-assisted analysis of Netflix/Hystrix@5ce3bc58c3 (2026-08-14).
Data as JSON: /api/errors/7426805b0880da47.
Report an issue: GitHub.