{"record":{"id":"f1eeb15ef3f105b2","repo":"lysine-dev/retrofit","slug":"response-must-be-parameterized-as-response-foo-or-f1eeb1","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/rxjava2/src/main/java/retrofit2/adapter/rxjava2/RxJava2CallAdapterFactory.java","lineNumber":132,"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 RxJava2CallAdapter(\n        responseType, scheduler, isAsync, isResult, isBody, isFlowable, isSingle, isMaybe, false);\n  }","sourceCodeStart":114,"sourceCodeEnd":150,"githubUrl":"https://github.com/lysine-dev/retrofit/blob/d0b112dad073b7fe49c953ebc46ff1b424cb1e51/retrofit-adapters/rxjava2/src/main/java/retrofit2/adapter/rxjava2/RxJava2CallAdapterFactory.java#L114-L150","documentation":"For RxJava 2.x methods declared as e.g. Observable<Response<...>>, the nested Response must be generic so the adapter can extract the body type. A raw Response leaves no deserialization target, so RxJava2CallAdapterFactory throws IllegalStateException when the inner observableType is Response.class but not a ParameterizedType.","triggerScenarios":"A method like `Observable<Response> getUser();` — outer type parameterized, inner Response raw. Thrown after `getRawType(observableType) == Response.class` when observableType is not a ParameterizedType.","commonSituations":"Adding the Response wrapper for status/headers and forgetting the body generic; partial refactor.","solutions":["Parameterize Response: `Single<Response<User>> getUser(@Path(\"id\") long id);`","Drop Response for body-only: `Single<User> getUser(@Path(\"id\") long id);`"],"exampleFix":"// before\nSingle<Response> getUser(@Path(\"id\") long id);\n// after\nSingle<Response<User>> getUser(@Path(\"id\") long id);","handlingStrategy":"validation","validationCode":"import java.lang.reflect.*;\nstatic void assertRx2ResponseParameterized(Class<?> iface) {\n  for (Method m : iface.getDeclaredMethods()) {\n    if (!(m.getGenericReturnType() instanceof ParameterizedType)) continue;\n    Type inner = ((ParameterizedType) m.getGenericReturnType()).getActualTypeArguments()[0];\n    if (inner.getTypeName().startsWith(\"retrofit2.Response\") && !(inner instanceof ParameterizedType)) {\n      throw new AssertionError(\"Raw nested Response on \" + m);\n    }\n  }\n}","typeGuard":null,"tryCatchPattern":"try {\n  Single<Response<User>> s = service.getUser(id);\n} catch (IllegalStateException e) {\n  throw new IllegalStateException(\"Nested Response return type is raw: \" + e.getMessage(), e);\n}","preventionTips":["Fail builds on raw types (-Xlint:rawtypes).","Unit-test that nested Response types are parameterized.","Use body-only form unless status/headers are needed."],"tags":["retrofit","rxjava2","generics","java","type-system","response"],"backgroundTag":null,"analyzedSha":"d0b112dad073b7fe49c953ebc46ff1b424cb1e51","analyzedAt":"2026-08-13T23:49:47.955Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}