Netflix/Hystrix · error · IllegalStateException
unsupported rx type: {}
Error message
unsupported rx type: {} What it means
GenericObservableCommand.toObservable accepts only rx.Observable, rx.Completable, or rx.Single (RxJava 1.x types) as the user action's return value; anything else throws IllegalStateException. It exists because observable commands may be declared with several rx return shapes, and the bridge must convert each to Observable — an unrecognized type cannot be converted.
Source
Thrown at hystrix-contrib/hystrix-javanica/src/main/java/com/netflix/hystrix/contrib/javanica/command/GenericObservableCommand.java:176
return false;
}
for (Class<? extends Throwable> ignoreException : ignoreExceptions) {
if (ignoreException.isAssignableFrom(throwable.getClass())) {
return true;
}
}
return false;
}
private Observable toObservable(Object obj) {
if (Observable.class.isAssignableFrom(obj.getClass())) {
return (Observable) obj;
} else if (Completable.class.isAssignableFrom(obj.getClass())) {
return ((Completable) obj).toObservable();
} else if (Single.class.isAssignableFrom(obj.getClass())) {
return ((Single) obj).toObservable();
} else {
throw new IllegalStateException("unsupported rx type: " + obj.getClass());
}
}
}
View on GitHub (pinned to 5ce3bc58c3)
Solutions
- Return rx.Observable/rx.Single/rx.Completable (RxJava 1.x) from methods executed in observable mode with hystrix-javanica.
- Convert other async types at the boundary: e.g. wrap CompletableFuture with Observable.from(future), or Reactor mono -> Observable via mono.toFuture() bridging or adapter libraries.
- If the codebase has moved to RxJava2/Reactor, prefer a Hystrix adaptation layer (e.g. HystrixObservableCommand subclass written manually) or migrate off Javanica for those methods.
Example fix
// before (RxJava2 leaking into javanica)
@HystrixCommand
public io.reactivex.Single<User> getUser(String id) { ... }
// after
@HystrixCommand
public rx.Single<User> getUser(String id) { ... }
// or bridge: rx.Observable.fromFuture(completableFuture) Defensive patterns
Strategy: validation
Validate before calling
static void assertRxJava1ReturnTypes(Class<?> clazz) {
for (Method m : clazz.getMethods()) {
Class<?> rt = m.getReturnType();
if (rt.getName().startsWith("io.reactivex.") || rt.getName().startsWith("reactor.")) {
if (m.isAnnotationPresent(HystrixCommand.class))
throw new IllegalStateException(m + " returns " + rt + " — hystrix-javanica only supports rx.* (RxJava1) types");
}
}
} Type guard
static boolean isSupportedRxType(Class<?> t) {
return rx.Observable.class.isAssignableFrom(t)
|| rx.Completable.class.isAssignableFrom(t)
|| rx.Single.class.isAssignableFrom(t);
} Try / catch
try { commandObservable = toObservable(actionResult); } catch (IllegalStateException e) { if (e.getMessage().startsWith("unsupported rx type")) log.error("action returned {} — convert to rx.Observable/Single/Completable (RxJava1)", resultClass); throw e; } Prevention
- Standardize on RxJava 1 rx.* types for any method executed through hystrix-javanica observable mode.
- Ban io.reactivex/reactor imports in Hystrix-annotated service classes via ArchUnit/checkstyle.
- Bridge CompletableFuture/Reactor at the adapter layer with Observable.from(...) rather than leaking them into commands.
When it happens
Trigger: An @HystrixCommand method executed in observable mode whose action returns an RxJava 2 type (io.reactivex.Observable/Single/Flowable/Completable), a java.util.concurrent.CompletableFuture, a plain value via a custom setup, or reactor's Flux/Mono — none of which are rx.* classes.
Common situations: Migrating a service from RxJava1 to RxJava2 while hystrix-javanica (built against RxJava1) is still in place; mixing Reactor and Hystrix in Spring WebFlux-era code; returning CompletableFuture from an observe-mode command.
Related errors
- fallback cannot return Observable if command isn't observabl
- Command should implement {} interface to execute in: {} mode
- Command should implement {} interface to execute in observab
- return type of '{}' method should be {};
- fallback cannot return 'void' if command return type is " +
AI-assisted analysis of Netflix/Hystrix@5ce3bc58c3 (2026-08-14).
Data as JSON: /api/errors/06d7da5a63212934.
Report an issue: GitHub.