{"record":{"id":"da5bd26c217267ef","repo":"lysine-dev/retrofit","slug":"name-return-type-must-be-parameterized-as-nam-da5bd2","errorCode":null,"errorMessage":"${name} return type must be parameterized as ${name}<Foo> or ${name}<? extends Foo>","messagePattern":"(.+?) return type must be parameterized as (.+?)<Foo> or (.+?)<\\? extends Foo>","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"retrofit-adapters/rxjava2/src/main/java/retrofit2/adapter/rxjava2/RxJava2CallAdapterFactory.java","lineNumber":118,"sourceCode":"      // can only be created with a single configuration.\n      return new RxJava2CallAdapter(\n          Void.class, scheduler, isAsync, false, true, false, false, false, true);\n    }\n\n    boolean isFlowable = rawType == Flowable.class;\n    boolean isSingle = rawType == Single.class;\n    boolean isMaybe = rawType == Maybe.class;\n    if (rawType != Observable.class && !isFlowable && !isSingle && !isMaybe) {\n      return null;\n    }\n\n    boolean isResult = false;\n    boolean isBody = false;\n    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) {","sourceCodeStart":100,"sourceCodeEnd":136,"githubUrl":"https://github.com/lysine-dev/retrofit/blob/d0b112dad073b7fe49c953ebc46ff1b424cb1e51/retrofit-adapters/rxjava2/src/main/java/retrofit2/adapter/rxjava2/RxJava2CallAdapterFactory.java#L100-L136","documentation":"Retrofit's RxJava 2.x adapter supports Observable, Flowable, Single, and Maybe (Completable is handled separately and needs no generic). Each of those must carry an element type; a raw type leaves the adapter unable to resolve what each emitted item is, so RxJava2CallAdapterFactory throws IllegalStateException, interpolating the actual class name ('Flowable', 'Single', 'Maybe', or 'Observable') into the message.","triggerScenarios":"A method with a raw return type such as `Flowable getUsers()`, `Single findUser()`, `Maybe maybeUser()`, or `Observable users()`. Thrown in get() when `returnType` is not a ParameterizedType; `name` is chosen from isFlowable/isSingle/isMaybe, defaulting to 'Observable'.","commonSituations":"Migrating from `Call<T>` to RxJava 2 and omitting the generic; mixing RxJava 1 and 2 types; suppress raw-types warnings.","solutions":["Parameterize the return type: `Observable<List<User>> getUsers();`, `Single<User> findUser(@Path(\"id\") long id);`, `Maybe<User> maybeUser(@Path(\"id\") long id);`, or `Flowable<List<User>> users();`","For no-payload calls use Completable: `Completable deleteUser(@Path(\"id\") long id);`","For full response/error packaging use `Observable<Response<User>>` or `Observable<Result<User>>`."],"exampleFix":"// before\nSingle findUser(@Path(\"id\") long id);\n// after\nSingle<User> findUser(@Path(\"id\") long id);","handlingStrategy":"validation","validationCode":"import java.lang.reflect.*;\nimport io.reactivex.*;\nstatic void assertRx2TypesParameterized(Class<?> iface) {\n  for (Method m : iface.getDeclaredMethods()) {\n    Type rt = m.getGenericReturnType();\n    Class<?> raw = erasure(rt);\n    if ((raw==Observable.class||raw==Flowable.class||raw==Single.class||raw==Maybe.class)\n        && !(rt instanceof ParameterizedType)) {\n      throw new AssertionError(\"Raw \" + raw.getSimpleName() + \" on \" + m);\n    }\n  }\n}","typeGuard":null,"tryCatchPattern":"try {\n  MyService svc = retrofit.create(MyService.class);\n  Single<User> s = svc.findUser(id);\n} catch (IllegalStateException e) {\n  throw new IllegalStateException(\"RxJava2 return type is raw on the service interface: \" + e.getMessage(), e);\n}","preventionTips":["Build with -Xlint:rawtypes so raw reactive types fail the build.","Use Completable for no-payload methods.","Add a reflection unit test over the service interface."],"tags":["retrofit","rxjava2","generics","java","type-system","observable"],"backgroundTag":null,"analyzedSha":"d0b112dad073b7fe49c953ebc46ff1b424cb1e51","analyzedAt":"2026-08-13T23:49:47.955Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}