{"id":"c3adff7287a1108c","repo":"square/retrofit","slug":"response-must-be-parameterized-as-response-foo-or-c3adff","errorCode":null,"errorMessage":"Response must be parameterized as Response<Foo> or Response<? extends Foo>","messagePattern":"Response must be parameterized as Response<Foo> or Response<\\? extends Foo>","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"retrofit-adapters/java8/src/main/java/retrofit2/adapter/java8/Java8CallAdapterFactory.java","lineNumber":80,"sourceCode":"      Type returnType, Annotation[] annotations, Retrofit retrofit) {\n    if (getRawType(returnType) != CompletableFuture.class) {\n      return null;\n    }\n    if (!(returnType instanceof ParameterizedType)) {\n      throw new IllegalStateException(\n          \"CompletableFuture return type must be parameterized\"\n              + \" as CompletableFuture<Foo> or CompletableFuture<? extends Foo>\");\n    }\n    Type innerType = getParameterUpperBound(0, (ParameterizedType) returnType);\n\n    if (getRawType(innerType) != Response.class) {\n      // Generic type is not Response<T>. Use it for body-only adapter.\n      return new BodyCallAdapter<>(innerType);\n    }\n\n    // Generic type is Response<T>. Extract T and create the Response version of the adapter.\n    if (!(innerType instanceof ParameterizedType)) {\n      throw new IllegalStateException(\n          \"Response must be parameterized\" + \" as Response<Foo> or Response<? extends Foo>\");\n    }\n    Type responseType = getParameterUpperBound(0, (ParameterizedType) innerType);\n    return new ResponseCallAdapter<>(responseType);\n  }\n\n  private static final class BodyCallAdapter<R> implements CallAdapter<R, CompletableFuture<R>> {\n    private final Type responseType;\n\n    BodyCallAdapter(Type responseType) {\n      this.responseType = responseType;\n    }\n\n    @Override\n    public Type responseType() {\n      return responseType;\n    }\n","sourceCodeStart":62,"sourceCodeEnd":98,"githubUrl":"https://github.com/square/retrofit/blob/d0b112dad073b7fe49c953ebc46ff1b424cb1e51/retrofit-adapters/java8/src/main/java/retrofit2/adapter/java8/Java8CallAdapterFactory.java#L62-L98","documentation":"Thrown by Java8CallAdapterFactory when the CompletableFuture is parameterized but its argument is raw `Response` (e.g. `CompletableFuture<Response>`). The factory needs `Response<T>` to extract T for deserialization; the raw inner type fails the check at Java8CallAdapterFactory.java:79.","triggerScenarios":"A service method returns `CompletableFuture<Response>` (raw Response) instead of `CompletableFuture<Response<Foo>>`.","commonSituations":"Switching a body return to a Response-wrapped return and dropping the inner type argument; autocompleting Response without generics; refactoring without re-running the wiring test.","solutions":["Parameterize the inner Response: `CompletableFuture<Response<User>> getUser();`.","Or drop the Response wrapper entirely: `CompletableFuture<User> getUser();`.","Prefer the built-in CompletableFuture support over the deprecated factory."],"exampleFix":"// before\n@GET(\"users/{id}\")\nCompletableFuture<Response> getUser(@Path(\"id\") String id);\n\n// after\n@GET(\"users/{id}\")\nCompletableFuture<Response<User>> getUser(@Path(\"id\") String id);","handlingStrategy":"validation","validationCode":"// Check for raw retrofit2.Response as a direct type argument of CompletableFuture.\nfor (Method m : MyService.class.getDeclaredMethods()) {\n    Type rt = m.getGenericReturnType();\n    if (rt instanceof ParameterizedType) {\n        Type arg = ((ParameterizedType) rt).getActualTypeArguments()[0];\n        if (arg == retrofit2.Response.class) {\n            throw new IllegalStateException(m + \" uses raw Response inside CompletableFuture.\");\n        }\n    }\n}","typeGuard":null,"tryCatchPattern":"// Fail loud in a wiring test:\ntry {\n    retrofit.create(MyService.class).getUser(\"1\");\n} catch (IllegalStateException e) {\n    if (e.getMessage().contains(\"Response must be parameterized\")) {\n        throw new IllegalStateException(\"Fix raw Response<> inside CompletableFuture in MyService.\", e);\n    }\n    throw e;\n}","preventionTips":["Always carry the body type when introducing Response<>.","Drop the deprecated explicit factory if possible.","Keep an end-to-end smoke test per service interface."],"tags":["retrofit","java8","java","reflection","response-wrapper","deprecated"],"analyzedSha":"d0b112dad073b7fe49c953ebc46ff1b424cb1e51","analyzedAt":"2026-08-04T19:12:59.096Z","schemaVersion":2}