{"record":{"id":"b6cad7296bf72864","repo":"lysine-dev/retrofit","slug":"response-must-be-parameterized-as-response-foo-or-b6cad7","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/scala/src/main/java/retrofit2/adapter/scala/ScalaCallAdapterFactory.java","lineNumber":76,"sourceCode":"  @Override\n  public @Nullable CallAdapter<?, ?> get(\n      Type returnType, Annotation[] annotations, Retrofit retrofit) {\n    if (getRawType(returnType) != Future.class) {\n      return null;\n    }\n    if (!(returnType instanceof ParameterizedType)) {\n      throw new IllegalStateException(\n          \"Future return type must be parameterized as Future<Foo> or Future<? 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    if (!(innerType instanceof ParameterizedType)) {\n      throw new IllegalStateException(\n          \"Response must be parameterized as Response<Foo> or Response<? extends Foo>\");\n    }\n\n    Type responseType = getParameterUpperBound(0, (ParameterizedType) innerType);\n    return new ResponseCallAdapter<>(responseType);\n  }\n}\n","sourceCodeStart":58,"sourceCodeEnd":84,"githubUrl":"https://github.com/lysine-dev/retrofit/blob/d0b112dad073b7fe49c953ebc46ff1b424cb1e51/retrofit-adapters/scala/src/main/java/retrofit2/adapter/scala/ScalaCallAdapterFactory.java#L58-L84","documentation":"Thrown by ScalaCallAdapterFactory.get() when the method returns Future<Response> with a raw inner Response. The factory resolved the outer Future's type argument (innerType) and found it is Response.class, so it now requires innerType itself to be a ParameterizedType so it can extract the concrete body type to deserialize. A raw Response yields no body type.","triggerScenarios":"A Retrofit interface method declared as Future<Response> getUser(...) — the outer Future is parameterized but its argument is the raw retrofit2.Response class. After the `getRawType(innerType) != Response.class` check passes, the `innerType instanceof ParameterizedType` check fails and throws.","commonSituations":"Wanting access to headers/status code via Response but forgetting the body generic, or converting a Future<User> method to Future<Response> during a refactor and stopping one level short.","solutions":["Parameterize the inner Response: change Future<Response> to Future<Response<User>>.","If you only need the deserialized body, drop Response entirely and return Future<User>.","Recompile so the corrected signature is re-evaluated when Retrofit builds the call adapter."],"exampleFix":"// before\n@GET(\"users/{id}\")\nFuture<Response> getUser(@Path(\"id\") String id);\n\n// after\n@GET(\"users/{id}\")\nFuture<Response<User>> getUser(@Path(\"id\") String id);","handlingStrategy":"validation","validationCode":"// Signature discipline; no per-call pre-check. Catch at Retrofit.create() in a unit test.\n// Static check that an outer Future<Response> carries a parameterized Response:\nMethod m = ApiService.class.getMethod(\"getUser\", String.class);\nType rt = m.getGenericReturnType();\nif (rt instanceof ParameterizedType) {\n  Type inner = ((ParameterizedType) rt).getActualTypeArguments()[0];\n  if (inner == retrofit2.Response.class) {\n    throw new AssertionError(\"getUser() returns Future<Response>; parameterize the Response.\");\n  }\n}","typeGuard":"// Enforce in Scala/Java by always declaring the inner type explicitly:\n//   Future<Response<User>> rather than Future<Response>.","tryCatchPattern":"try {\n  ApiService api = retrofit.create(ApiService.class);\n} catch (IllegalStateException e) {\n  if (e.getMessage() != null && e.getMessage().contains(\"Response must be parameterized\")) {\n    throw new ConfigurationException(\"Service interface has Future<Response> with raw Response\", e);\n  }\n  throw e;\n}","preventionTips":["When wrapping a body type in Future<Response<...>>, always supply the body generic.","Treat raw retrofit2.Response in any signature as a compile-time smell.","Unit-test Retrofit.create() against the Scala-backed service to catch this early."],"tags":["retrofit","scala","type-parameterization","configuration"],"backgroundTag":null,"analyzedSha":"d0b112dad073b7fe49c953ebc46ff1b424cb1e51","analyzedAt":"2026-08-13T23:49:47.955Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}