Netflix/Hystrix · error · RuntimeException

Command should implement {} interface to execute in: {} mode

Error message

Command should implement {} interface to execute in: {} mode

What it means

When a command must be executed via queue()/execute() (SYNCHRONOUS or ASYNCHRONOUS execution types), the created HystrixInvokable must implement HystrixExecutable. Javanica throws this RuntimeException when the invokable built for the method is a HystrixObservableCommand-based object (which only implements HystrixObservable) but the derived execution type demands queue semantics — an execution-type/invokable-kind mismatch.

Source

Thrown at hystrix-contrib/hystrix-javanica/src/main/java/com/netflix/hystrix/contrib/javanica/command/CommandExecutor.java:75

                        && ExecutionType.ASYNCHRONOUS == metaHolder.getFallbackExecutionType()) {
                    return new FutureDecorator(executable.queue());
                }
                return executable.queue();
            }
            case OBSERVABLE: {
                HystrixObservable observable = castToObservable(invokable);
                return ObservableExecutionMode.EAGER == metaHolder.getObservableExecutionMode() ? observable.observe() : observable.toObservable();
            }
            default:
                throw new RuntimeException("unsupported execution type: " + executionType);
        }
    }

    private static HystrixExecutable castToExecutable(HystrixInvokable invokable, ExecutionType executionType) {
        if (invokable instanceof HystrixExecutable) {
            return (HystrixExecutable) invokable;
        }
        throw new RuntimeException("Command should implement " + HystrixExecutable.class.getCanonicalName() + " interface to execute in: " + executionType + " mode");
    }

    private static HystrixObservable castToObservable(HystrixInvokable invokable) {
        if (invokable instanceof HystrixObservable) {
            return (HystrixObservable) invokable;
        }
        throw new RuntimeException("Command should implement " + HystrixObservable.class.getCanonicalName() + " interface to execute in observable mode");
    }

}

View on GitHub (pinned to 5ce3bc58c3)

Solutions

  1. Make return types consistent: if the underlying action returns rx Observable/Single/Completable, declare the annotated method (or collapser chain) with Observable-compatible execution, e.g. return Observable<T>.
  2. If the method should be sync/async, make the action return a plain value (or use toBlocking().single() style bridging inside the action) so a GenericCommand is built.
  3. Audit custom HystrixCommandFactory/MetaHolderFactory overrides to confirm the invokable kind matches the execution type.

Example fix

// before
@HystrixCommand
public Single<User> getUser(String id) { ... }   // observable invokable
... userService.getUser(id).toBlocking().value(); // invoked via async path mismatch

// after
@HystrixCommand
public User getUser(String id) { return loadUser(id); }  // sync execution
// or declare: public Observable<User> getUser(String id)
Defensive patterns

Strategy: validation

Validate before calling

static boolean rxTypesConsistentWithExecution(Method m) {
    Class<?> rt = m.getReturnType();
    boolean rx = rx.Observable.class.isAssignableFrom(rt) || rx.Single.class.isAssignableFrom(rt) || rx.Completable.class.isAssignableFrom(rt);
    boolean syncAsync = !rx;
    // sync/async methods must return plain types or Future; rx types must be served via Observable execution
    return true; // enforce in code review: rx types only with observable-style declarations
}

Try / catch

try { ... } catch (RuntimeException e) when 'Command should implement' in message → fail fast and log invokable class + executionType; this is a wiring/version mismatch, not transient.

Prevention

When it happens

Trigger: A command meta-holder built for observable-style execution (e.g. GenericObservableCommand wrapping a Single/Completable/observe-mode action) but dispatched with ExecutionType.SYNCHRONOUS or ASYNCHRONOUS — typically from a collapser whose batch command returns rx types while the collapser method returns plain/Future types, or custom factories pairing the wrong invokable with the wrong execution type.

Common situations: Mixing rx return types (Single/Completable) on batch methods with non-Observable collapser signatures; custom HystrixCommandFactory extensions; version-skewed classpaths producing inconsistent factory selection.

Related errors


AI-assisted analysis of Netflix/Hystrix@5ce3bc58c3 (2026-08-14). Data as JSON: /api/errors/afcc445f48d80db2. Report an issue: GitHub.