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

  1. Check the hint for the exact required return type
  2. 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)
  3. If multiple commands share a fallback name, split them into type-specific fallback methods
  4. 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

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


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