{"record":{"id":"5657e8d26c1484b3","repo":"lysine-dev/retrofit","slug":"result-must-be-parameterized-as-result-foo-or-res-5657e8","errorCode":null,"errorMessage":"Result must be parameterized as Result<Foo> or Result<? extends Foo>","messagePattern":"Result must be parameterized as Result<Foo> or Result<\\? extends Foo>","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"retrofit-adapters/rxjava3/src/main/java/retrofit2/adapter/rxjava3/RxJava3CallAdapterFactory.java","lineNumber":143,"sourceCode":"              + \" 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  }\n}\n","sourceCodeStart":125,"sourceCodeEnd":157,"githubUrl":"https://github.com/lysine-dev/retrofit/blob/d0b112dad073b7fe49c953ebc46ff1b424cb1e51/retrofit-adapters/rxjava3/src/main/java/retrofit2/adapter/rxjava3/RxJava3CallAdapterFactory.java#L125-L157","documentation":"Thrown by RxJava3CallAdapterFactory when the reactive return type's argument is a raw retrofit2.adapter.rxjava3.Result. Result<T> is this adapter's wrapper that emits either the Response body or a thrown exception so subscribers receive both as stream values. The factory needs Result parameterized so it can resolve the inner body type to deserialize.","triggerScenarios":"A Retrofit interface method declared as Observable<Result>, Flowable<Result>, Single<Result>, or Maybe<Result> (raw Result). During Retrofit.build()/service-interface scanning the branch `rawObservableType == Result.class` runs, finds observableType is a Class not a ParameterizedType, and throws.","commonSituations":"Switching a stream from body-only Observable<User> to error-capturing Observable<Result> and forgetting the generic, or misreading the Result class javadoc and assuming it is self-describing without a type argument.","solutions":["Parameterize Result with the body type: change Observable<Result> to Observable<Result<User>>.","If you actually want the raw retrofit2.Response, use Observable<Response<User>> instead of Result.","If you only need the body and prefer exceptions to propagate down onError, return Observable<User> directly.","Recompile the module so the corrected signature is picked up at Retrofit.validateEagerly() time."],"exampleFix":"// before\n@GET(\"users/{id}\")\nObservable<Result> getUser(@Path(\"id\") String id);\n\n// after\n@GET(\"users/{id}\")\nObservable<Result<User>> getUser(@Path(\"id\") String id);","handlingStrategy":"validation","validationCode":"// The guard is method-signature discipline; there is no per-call runtime pre-check.\n// Verify at test time that Result is parameterized:\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.adapter.rxjava3.Result.class) {\n    throw new AssertionError(\"getUser() returns raw Observable<Result>; parameterize it.\");\n  }\n}","typeGuard":"// Kotlin reified helper so Result is always parameterized at the call site.\ninline fun <reified T> resultObservableType(): Type =\n    TypeToken<Observable<Result<T>>>() {}.type","tryCatchPattern":"// Fires at Retrofit.create() time. Prefer fixing the signature; isolate like this if needed:\ntry {\n  ApiService api = retrofit.create(ApiService.class);\n} catch (IllegalStateException e) {\n  if (e.getMessage() != null && e.getMessage().contains(\"Result must be parameterized\")) {\n    throw new ConfigurationException(\"Service interface has a raw Observable<Result> method\", e);\n  }\n  throw e;\n}","preventionTips":["Always parameterize retrofit2.adapter.rxjava3.Result with the body type.","Treat IDE raw-types warnings as errors for service interface files.","Run Retrofit.create() in a unit test with eager validation to catch this before runtime."],"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"}