OpenFeign/feign · error · IllegalArgumentException
Expected a Class, ParameterizedType, or GenericArrayType…
Error message
Expected a Class, ParameterizedType, or GenericArrayType, but <{type}> is of type {className} What it means
Types.getRawType() resolves the raw Class behind a java.lang.reflect Type but only understands Class, ParameterizedType, GenericArrayType and WildcardType. Any other Type implementation (or null) triggers this IllegalArgumentException naming the offending type and its class.
Solutions
- Pass a Class, ParameterizedType, or GenericArrayType instead of a TypeVariable
- Resolve type variables to concrete types first (e.g. via Types.resolve or getGenericSuperclass)
- Null-check the Type before calling getRawType
- If the type comes from a framework, capture the concrete body type at build time
Example fix
// before Type t = method.getTypeParameters()[0]; // TypeVariable -> IllegalArgumentException // after Type t = method.getGenericReturnType(); // ParameterizedType/Class Class<?> raw = Types.getRawType(t);
Defensive patterns
Strategy: type-guard
Validate before calling
if (type == null || type instanceof TypeVariable) throw new IllegalArgumentException("Use a concrete Class/ParameterizedType, got: " + type); Type guard
static boolean isResolvable(Type t) { return t instanceof Class || t instanceof ParameterizedType || t instanceof GenericArrayType || t instanceof WildcardType; } Try / catch
try { Class<?> raw = Types.getRawType(type); } catch (IllegalArgumentException e) { /* fall back to Types.resolve with declaring context */ } Prevention
- Never pass TypeVariables from generic methods directly
- Resolve generics against the concrete subclass before calling
- Null-check types from reflection APIs
When it happens
Trigger: Passing a TypeVariable, custom Type implementation, or null to Types.getRawType (directly or via encoders/contracts that use it), e.g. feeding a generic method's TypeVariable into encoder type resolution.
Common situations: Custom Encoder/Decoder implementations calling Types.getRawType on unbound type variables; proxy/reflection frameworks producing exotic Type implementations; version changes where types flow differently through the contract.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- Cannot generate exception - check constructor parameter…
- Too many constructors marked with @FeignExceptionConstructor
- Cannot find any suitable constructor in class
- Cannot access constructor
- Cannot instantiate exception with constructor
AI-assisted analysis of OpenFeign/feign@e2a1e27560 (2026-09-10).
Data as JSON: /api/errors/06291d343ea9bb73.
Report an issue: GitHub.
Appendix: source
Thrown at core/src/main/java/feign/Types.java:74
throw new IllegalArgumentException();
}
return (Class<?>) rawType;
} else if (type instanceof GenericArrayType) {
Type componentType = ((GenericArrayType) type).getGenericComponentType();
return Array.newInstance(getRawType(componentType), 0).getClass();
} else if (type instanceof TypeVariable) {
// We could use the variable's bounds, but that won't work if there are multiple. Having a raw
// type that's more general than necessary is okay.
return Object.class;
} else if (type instanceof WildcardType) {
return getRawType(((WildcardType) type).getUpperBounds()[0]);
} else {
String className = type == null ? "null" : type.getClass().getName();
throw new IllegalArgumentException(
"Expected a Class, ParameterizedType, or "
+ "GenericArrayType, but <"
+ type
+ "> is of type "
+ className);
}
}
/** Returns true if {@code a} and {@code b} are equal. */
static boolean equals(Type a, Type b) {
if (a == b) {
return true; // Also handles (a == null && b == null).
} else if (a instanceof Class) {
return a.equals(b); // Class already specifies equals().
} else if (a instanceof ParameterizedType) {
if (!(b instanceof ParameterizedType)) {View on GitHub (pinned to e2a1e27560)