OpenFeign/feign · error · IllegalArgumentException
Type must be an interface
Error message
Type must be an interface: ${type} What it means
Validation in TargetSpecificationVerifier.verify: the type of the given Target is not an interface, so Feign's dynamic-proxy-based client cannot be constructed. Feign creates a JDK Proxy over the target's interface; a class (or primitive/array) type is unsupported input and the target can never be instantiated.
Solutions
- Define the API as an interface and point the Target at that interface type
- Use Feign.builder().target(TypeApi.class, url) with an interface rather than a concrete class
- If you have a concrete class, extract an interface for its remote methods
- Check for accidental use of getClass() or an implementation type when constructing the Target
Defensive patterns
Strategy: validation
When it happens
Trigger: Thrown at core/src/main/java/feign/ReflectiveFeign.java:235 when the library encounters an invalid state.
Common situations: See trigger scenarios.
AI-assisted analysis of OpenFeign/feign@e2a1e27560 (2026-09-10).
Data as JSON: /api/errors/4c52dfef71943906.
Report an issue: GitHub.
Appendix: source
Thrown at core/src/main/java/feign/ReflectiveFeign.java:235
}
private MethodHandler createMethodHandler(
final Target<?> target, final MethodMetadata md, final C requestContext) {
if (md.isIgnored()) {
return args -> {
throw new IllegalStateException(md.configKey() + " is not a method handled by feign");
};
}
return factory.create(target, md, requestContext);
}
}
private static class TargetSpecificationVerifier {
public static <T> void verify(Target<T> target) {
Class<T> type = target.type();
if (!type.isInterface()) {
throw new IllegalArgumentException("Type must be an interface: " + type);
}
for (final Method m : type.getMethods()) {
final Class<?> retType = m.getReturnType();
if (!CompletableFuture.class.isAssignableFrom(retType)) {
continue; // synchronous case
}
if (retType != CompletableFuture.class) {
throw new IllegalArgumentException(
"Method return type is not CompleteableFuture: "
+ getFullMethodName(type, retType, m));
}
final Type genRetType = m.getGenericReturnType();
if (!(genRetType instanceof ParameterizedType)) {View on GitHub (pinned to e2a1e27560)