Netflix/Hystrix · error · FallbackDefinitionException
Incompatible return types. \nCommand method: " + commandMeth
Error message
Incompatible return types. \nCommand method: " + commandMethod + ";\nFallback method: " + fallbackMethod + ";\n" + "Hint: Fallback method '" + fallbackMethod + "' must return: " + commandReturnType + " or its subclass"
What it means
validatePlainReturnType checks the RAW (non-generic) return types of command and fallback via Class.isAssignableFrom. If the fallback's raw return type is not the command's return type or a subclass, FallbackDefinitionException is thrown with the 'Incompatible return types ... must return: <type> or its subclass' hint (message template includes both method signatures).
Source
Thrown at hystrix-contrib/hystrix-javanica/src/main/java/com/netflix/hystrix/contrib/javanica/utils/FallbackMethod.java:192
}
}
msg.add(String.format(error.reason + "\n" + extraHint + "Command type literal pos: %s; Fallback type literal pos: %s",
positionAsString(error.commandType, commandParametrizedTypes),
positionAsString(error.fallbackType, fallbackParametrizedTypes)));
}
throw new FallbackDefinitionException(createErrorMsg(commandMethod, method, StringUtils.join(msg, "\n")));
}
}
validatePlainReturnType(commandMethod, fallbackMethod);
}
private void validatePlainReturnType(Method commandMethod, Method fallbackMethod) {
validatePlainReturnType(commandMethod.getReturnType(), fallbackMethod.getReturnType(), commandMethod, fallbackMethod);
}
private void validatePlainReturnType(Class<?> commandReturnType, Class<?> fallbackReturnType, Method commandMethod, Method fallbackMethod) {
if (!commandReturnType.isAssignableFrom(fallbackReturnType)) {
throw new FallbackDefinitionException(createErrorMsg(commandMethod, fallbackMethod, "Fallback method '"
+ fallbackMethod + "' must return: " + commandReturnType + " or its subclass"));
}
}
private void validateParametrizedType(Type commandReturnType, Type fallbackReturnType, Method commandMethod, Method fallbackMethod) {
if (!commandReturnType.equals(fallbackReturnType)) {
throw new FallbackDefinitionException(createErrorMsg(commandMethod, fallbackMethod, "Fallback method '"
+ fallbackMethod + "' must return: " + commandReturnType + " or its subclass"));
}
}
private String createErrorMsg(Method commandMethod, Method fallbackMethod, String hint) {
return "Incompatible return types. \nCommand method: " + commandMethod + ";\nFallback method: " + fallbackMethod + ";\n"
+ (StringUtils.isNotBlank(hint) ? "Hint: " + hint : "");
}
private static final Result SUCCESS = Result.success();
View on GitHub (pinned to 5ce3bc58c3)
Solutions
- Check the hint for the exact required return type
- Change the fallback's return type to the command's type or a subclass of it (assignability direction: fallback type must fit INTO command type)
- If multiple commands share a fallback name, split them into type-specific fallback methods
- Cover fallback definitions with a startup smoke test in CI
Example fix
// before
@HystrixCommand
public User getUser(String id) { ... }
private String getUserFallback(String id) { return "unknown"; }
// after
@HystrixCommand
public User getUser(String id) { ... }
private User getUserFallback(String id) { return User.EMPTY; } Defensive patterns
Strategy: validation
Validate before calling
Class<?> cmdRet = commandMethod.getReturnType();
Class<?> fbRet = fallbackMethod.getReturnType();
if (!cmdRet.isAssignableFrom(fbRet)) {
throw new IllegalStateException("Fallback " + fallbackMethod + " must return " + cmdRet + " or subclass");
} Type guard
boolean fallbackRawTypeOk(Class<?> commandReturnType, Class<?> fallbackReturnType) {
return commandReturnType.isAssignableFrom(fallbackReturnType);
} Try / catch
catch (FallbackDefinitionException e) { log.error("{}", e.getMessage()); failBuild(e); } Prevention
- Change fallback return type together with command return type in the same commit
- Return the command's declared type (or exact subclass) from fallbacks — never a String/Optional stand-in
- CI smoke test invoking each command validates all pairs
When it happens
Trigger: @HystrixCommand User getUser() with fallback String getUserFallback(); or command returns interface User while fallback returns a class implementing a different interface.
Common situations: Fallback written to return a defensive default of the wrong type (e.g. Optional.empty vs null-bearing DTO); refactoring the command's return type without updating fallbacks; overloads sharing a fallback name with different return types.
Related errors
- fallback cannot return Future if the fallback isn't command
- fallback cannot return Future if command isn't asynchronous.
- fallback cannot return Observable if command isn't observabl
- fallback cannot return 'void' if command return type is " +
- Incompatible return types. \nCommand method: " + commandMeth
AI-assisted analysis of Netflix/Hystrix@5ce3bc58c3 (2026-08-14).
Data as JSON: /api/errors/91fa914505f8cb8f.
Report an issue: GitHub.