{"record":{"id":"b0485cf41357d9f9","repo":"lysine-dev/retrofit","slug":"response-must-be-parameterized-as-response-foo-or-b0485c","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/rxjava3/src/main/java/retrofit2/adapter/rxjava3/RxJava3CallAdapterFactory.java","lineNumber":137,"sourceCode":"    Type responseType;\n    if (!(returnType instanceof ParameterizedType)) {\n      String name =\n          isFlowable ? \"Flowable\" : isSingle ? \"Single\" : isMaybe ? \"Maybe\" : \"Observable\";\n      throw new IllegalStateException(\n          name\n              + \" return type must be parameterized\"\n              + \" as \"\n              + name\n              + \"<Foo> or \"\n              + name\n              + \"<? extends Foo>\");\n    }\n\n    Type observableType = getParameterUpperBound(0, (ParameterizedType) returnType);\n    Class<?> rawObservableType = getRawType(observableType);\n    if (rawObservableType == Response.class) {\n      if (!(observableType instanceof ParameterizedType)) {\n        throw new IllegalStateException(\n            \"Response must be parameterized\" + \" as Response<Foo> or Response<? extends Foo>\");\n      }\n      responseType = getParameterUpperBound(0, (ParameterizedType) observableType);\n    } else if (rawObservableType == Result.class) {\n      if (!(observableType instanceof ParameterizedType)) {\n        throw new IllegalStateException(\n            \"Result must be parameterized\" + \" as Result<Foo> or Result<? extends Foo>\");\n      }\n      responseType = getParameterUpperBound(0, (ParameterizedType) observableType);\n      isResult = true;\n    } else {\n      responseType = observableType;\n      isBody = true;\n    }\n\n    return new RxJava3CallAdapter(\n        responseType, scheduler, isAsync, isResult, isBody, isFlowable, isSingle, isMaybe, false);\n  }","sourceCodeStart":119,"sourceCodeEnd":155,"githubUrl":"https://github.com/lysine-dev/retrofit/blob/d0b112dad073b7fe49c953ebc46ff1b424cb1e51/retrofit-adapters/rxjava3/src/main/java/retrofit2/adapter/rxjava3/RxJava3CallAdapterFactory.java#L119-L155","documentation":"Thrown by RxJava3CallAdapterFactory while resolving the CallAdapter for a service method whose return type's type argument is a raw retrofit2.Response. The factory unwraps the outer reactive type (Observable/Flowable/Single/Maybe) via getParameterUpperBound, and when that bound is Response.class it requires Response itself to carry a concrete body type. A bare Response gives the adapter no body type to deserialize into, so it refuses to build the adapter.","triggerScenarios":"A Retrofit interface method declared as Observable<Response>, Flowable<Response>, Single<Response>, or Maybe<Response> (raw Response, no generic argument). The factory's get() is invoked at Retrofit.build() time when it scans the service interface; the check `observableType instanceof ParameterizedType` fails for the raw class and throws IllegalStateException.","commonSituations":"Copying a method signature and forgetting to parameterize Response, refactoring a method that returned Observable<User> into Observable<Response> to gain access to headers/status, or IDE auto-import picking the raw retrofit2.Response type and silently dropping the generic.","solutions":["Parameterize the Response in the return type, e.g. change Observable<Response> to Observable<Response<User>>.","If you want the body only, drop Response entirely and return Observable<User>.","If you want both body and errors as a stream, switch to Observable<Result<User>> which the factory also supports.","Clean/rebuild the project so the corrected interface is recompiled before Retrofit.validateEagerly() inspects it."],"exampleFix":"// before\n@GET(\"users/{id}\")\nObservable<Response> getUser(@Path(\"id\") String id);\n\n// after\n@GET(\"users/{id}\")\nObservable<Response<User>> getUser(@Path(\"id\") String id);","handlingStrategy":"validation","validationCode":"// Verify the service method signature at build time before Retrofit scans it.\n// In Java there is no runtime pre-check; the guard is compile-time discipline:\n//   - never write Observable<Response> / Flowable<Response> / Single<Response> / Maybe<Response>\n//   - always supply the body type: Observable<Response<BodyType>>\n//\n// Optional unit test that fails fast if a signature drifts to raw Response:\nMethod m = ApiService.class.getMethod(\"getUser\", String.class);\nType rt = m.getGenericReturnType();\nif (rt instanceof ParameterizedType) {\n  Type arg = ((ParameterizedType) rt).getActualTypeArguments()[0];\n  if (arg == retrofit2.Response.class) {\n    throw new AssertionError(\"getUser() returns raw Observable<Response>; parameterize it.\");\n  }\n}","typeGuard":"// Kotlin reified helper to enforce Response is parameterized at the call site.\ninline fun <reified T> responseObservableType(): Type =\n    TypeToken<Observable<Response<T>>>() {}.type  // compile error if T omitted","tryCatchPattern":"// This error fires at Retrofit.create()/build() time, not per-call.\n// Prefer fixing the signature; if you must isolate it, catch during service creation:\ntry {\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 a raw Observable<Response> method\", e);\n  }\n  throw e;\n}","preventionTips":["Always parameterize retrofit2.Response with a body type in reactive return signatures.","Enable IDE raw-types/unchecked warnings as errors so a raw Response surfaces immediately.","Add a unit test that calls Retrofit.create() with eager validation to catch signature errors before integration."],"tags":["retrofit","rxjava3","type-parameterization","configuration"],"backgroundTag":null,"analyzedSha":"d0b112dad073b7fe49c953ebc46ff1b424cb1e51","analyzedAt":"2026-08-13T23:49:47.955Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}