Netflix/Hystrix · error · FallbackDefinitionException
fallback cannot return 'void' if command return type is " +
Error message
fallback cannot return 'void' if command return type is " + Completable.class.getSimpleName()
What it means
When the @HystrixCommand method returns rx.Completable, Javanica permits the fallback to return any type that can wrap completion ('everything can be wrapped into completable') EXCEPT void. validateCompletableReturnType throws FallbackDefinitionException if the fallback's return type is Void.TYPE (primitive void), since there would be no value to complete the Completable with and no way to signal a fallback result.
Source
Thrown at hystrix-contrib/hystrix-javanica/src/main/java/com/netflix/hystrix/contrib/javanica/utils/FallbackMethod.java:156
validateReturnType(commandMethod, method);
}
}
}
private Type getFirstParametrizedType(Method m) {
Type gtype = m.getGenericReturnType();
if (gtype instanceof ParameterizedType) {
ParameterizedType pType = (ParameterizedType) gtype;
return pType.getActualTypeArguments()[0];
}
return null;
}
// everything can be wrapped into completable except 'void'
private void validateCompletableReturnType(Method commandMethod, Class<?> callbackReturnType) {
if (Void.TYPE == callbackReturnType) {
throw new FallbackDefinitionException(createErrorMsg(commandMethod, method, "fallback cannot return 'void' if command return type is " + Completable.class.getSimpleName()));
}
}
private void validateReturnType(Method commandMethod, Method fallbackMethod) {
if (isGenericReturnType(commandMethod)) {
List<Type> commandParametrizedTypes = flattenTypeVariables(commandMethod.getGenericReturnType());
List<Type> fallbackParametrizedTypes = flattenTypeVariables(fallbackMethod.getGenericReturnType());
Result result = equalsParametrizedTypes(commandParametrizedTypes, fallbackParametrizedTypes);
if (!result.success) {
List<String> msg = new ArrayList<String>();
for (Error error : result.errors) {
Optional<Type> parentKindOpt = getParentKind(error.commandType, commandParametrizedTypes);
String extraHint = "";
if (parentKindOpt.isPresent()) {
Type parentKind = parentKindOpt.get();
if (isParametrizedType(parentKind)) {
extraHint = "--> " + ((ParameterizedType) parentKind).getRawType().toString() + "<Ooops!>\n";
}View on GitHub (pinned to 5ce3bc58c3)
Solutions
- Change the fallback return type from void to Completable (or another wrappable type such as Observable/Single)
- In the Completable fallback, signal completion via Completable.complete() or an error via Completable.error(e) instead of relying on void return
- Keep a naming/convention check in code review for Completable commands' fallbacks
- Add a CI test that triggers the fallback path once so the definition is validated
Example fix
// before
@HystrixCommand
public Completable doWork() { ... }
private void doWorkFallback(Throwable e) { log(e); }
// after
@HystrixCommand
public Completable doWork() { ... }
private Completable doWorkFallback(Throwable e) { log(e); return Completable.complete(); } Defensive patterns
Strategy: validation
Validate before calling
Class<?> cmdRet = commandMethod.getReturnType();
if (Completable.class.isAssignableFrom(cmdRet) && fallbackMethod.getReturnType() == Void.TYPE) {
throw new IllegalStateException("Completable command requires non-void fallback: " + fallbackMethod);
} Try / catch
catch (FallbackDefinitionException e) { log.error("Completable command has void fallback: {}", e.getMessage()); failBuild(e); } Prevention
- For Completable commands, make fallbacks return Completable.complete()/error(e)
- Add code-review convention: no void fallbacks anywhere in Javanica code
- Cover the fallback path in tests, not just the happy path
When it happens
Trigger: @HystrixCommand Completable doWork() with a fallback declared as `void doWorkFallback(Throwable e)` (or parameterless void variant).
Common situations: Writing fallbacks for Completable-returning commands by analogy with void-returning commands; code-generation tools defaulting fallbacks to void; refactoring Observable commands to Completable while keeping void fallbacks.
Related errors
- fallback cannot return Observable if command isn't observabl
- fallback cannot return Future if the fallback isn't command
- fallback cannot return Future if command isn't asynchronous.
- Incompatible return types. \nCommand method: " + commandMeth
- Incompatible return types. \nCommand method: " + commandMeth
AI-assisted analysis of Netflix/Hystrix@5ce3bc58c3 (2026-08-14).
Data as JSON: /api/errors/b39ec051066992cc.
Report an issue: GitHub.