square/retrofit · error · IllegalStateException
Response must be parameterized as Response<Foo> or Response<
Error message
Response must be parameterized as Response<Foo> or Response<? extends Foo>
What it means
Thrown by GuavaCallAdapterFactory when the future IS parameterized, but its single type argument is the raw `Response` class (e.g. `ListenableFuture<Response>`). The factory detected Response as the inner type and then needs to extract the body type T from `Response<T>`; a raw Response leaves T unknown, so at GuavaCallAdapterFactory.java:80 it throws.
Source
Thrown at retrofit-adapters/guava/src/main/java/retrofit2/adapter/guava/GuavaCallAdapterFactory.java:81
Type returnType, Annotation[] annotations, Retrofit retrofit) {
if (getRawType(returnType) != ListenableFuture.class) {
return null;
}
if (!(returnType instanceof ParameterizedType)) {
throw new IllegalStateException(
"ListenableFuture return type must be parameterized"
+ " as ListenableFuture<Foo> or ListenableFuture<? extends Foo>");
}
Type innerType = getParameterUpperBound(0, (ParameterizedType) returnType);
if (getRawType(innerType) != Response.class) {
// Generic type is not Response<T>. Use it for body-only adapter.
return new BodyCallAdapter<>(innerType);
}
// Generic type is Response<T>. Extract T and create the Response version of the adapter.
if (!(innerType instanceof ParameterizedType)) {
throw new IllegalStateException(
"Response must be parameterized" + " as Response<Foo> or Response<? extends Foo>");
}
Type responseType = getParameterUpperBound(0, (ParameterizedType) innerType);
return new ResponseCallAdapter<>(responseType);
}
private static final class BodyCallAdapter<R> implements CallAdapter<R, ListenableFuture<R>> {
private final Type responseType;
BodyCallAdapter(Type responseType) {
this.responseType = responseType;
}
@Override
public Type responseType() {
return responseType;
}
View on GitHub (pinned to d0b112dad0)
Solutions
- Parameterize the inner Response with the body type: `ListenableFuture<Response<User>> getUser();`.
- If you do not actually need the Response wrapper, drop it and return `ListenableFuture<User>` directly.
- Rebuild; the factory will resolve responseType and return a ResponseCallAdapter.
Example fix
// before
@GET("users/{id}")
ListenableFuture<Response> getUser(@Path("id") String id);
// after
@GET("users/{id}")
ListenableFuture<Response<User>> getUser(@Path("id") String id); Defensive patterns
Strategy: validation
Validate before calling
// Scan service methods for a raw Response nested inside a future type.
for (Method m : MyService.class.getDeclaredMethods()) {
Type rt = m.getGenericReturnType();
if (rt instanceof ParameterizedType
&& ((ParameterizedType) rt).getRawType() == retrofit2.Response.class) {
throw new IllegalStateException(m + " uses raw Response; parameterize Response<T>.");
}
// also handle Response nested one level deep, e.g. ListenableFuture<Response>
} Try / catch
// Programming error -- do not silently swallow. Fail fast in a wiring test:
try {
retrofit.create(MyService.class).getUser("1");
} catch (IllegalStateException e) {
if (e.getMessage().contains("Response must be parameterized")) {
throw new IllegalStateException("Fix raw Response<> in MyService.", e);
}
throw e;
} Prevention
- When introducing Response<>, always carry the body type into it.
- Let the IDE's raw-types inspection flag this before runtime.
- Keep a unit test that exercises each service method to surface adapter errors at build time.
When it happens
Trigger: A service method returns `ListenableFuture<Response>` (raw Response) rather than `ListenableFuture<Response<Foo>>`. The check `innerType instanceof ParameterizedType` at line 80 fails because Response has no type arguments.
Common situations: Wrapping a return in Response to get status/headers but forgetting to also parameterize Response with the body type; refactoring a body return into a Response return and losing the inner generic; or autocompleting `Response` without its argument.
Related errors
- ListenableFuture return type must be parameterized as Listen
- CompletableFuture return type must be parameterized as Compl
- Response must be parameterized as Response<Foo> or Response<
- ${name} return type must be parameterized as ${name}<Foo> or
- Response must be parameterized as Response<Foo> or Response<
AI-assisted analysis of square/retrofit@d0b112dad0 (2026-08-04).
Data as JSON: /data/errors/a5876cd250f1c2d0.json.
Report an issue: GitHub.