{"record":{"id":"d601be3273c91702","repo":"Netflix/Hystrix","slug":"return-type-of-method-should-be","errorCode":null,"errorMessage":"return type of '{}' method should be {};","messagePattern":"return type of '(.+?)' method should be (.+?);","errorType":"validation","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"hystrix-contrib/hystrix-javanica/src/main/java/com/netflix/hystrix/contrib/javanica/command/closure/AbstractClosureFactory.java","lineNumber":65,"sourceCode":"            return createClosure(method.getName(), closureObj);\n        } catch (InvocationTargetException e) {\n            throw Throwables.propagate(e.getCause());\n        } catch (Exception e) {\n            throw Throwables.propagate(e);\n        }\n    }\n\n    /**\n     * Creates closure.\n     *\n     * @param rootMethodName the name of external method within which closure is created.\n     * @param closureObj     the instance of specific anonymous class\n     * @return new {@link Closure} instance\n     * @throws Exception\n     */\n    Closure createClosure(String rootMethodName, final Object closureObj) throws Exception {\n        if (!isClosureCommand(closureObj)) {\n            throw new RuntimeException(format(ERROR_TYPE_MESSAGE, rootMethodName,\n                    getClosureCommandType().getName()).getMessage());\n        }\n        Method closureMethod = closureObj.getClass().getMethod(INVOKE_METHOD);\n        return new Closure(closureMethod, closureObj);\n    }\n\n    /**\n     * Checks that closureObj is instance of necessary class.\n     *\n     * @param closureObj the instance of an anonymous class\n     * @return true of closureObj has expected type, otherwise - false\n     */\n    abstract boolean isClosureCommand(final Object closureObj);\n\n    /**\n     * Gets type of expected closure type.\n     *\n     * @return closure (anonymous class) type","sourceCodeStart":47,"sourceCodeEnd":83,"githubUrl":"https://github.com/Netflix/Hystrix/blob/5ce3bc58c38e7ca60ef2fe0e516e390e294ad941/hystrix-contrib/hystrix-javanica/src/main/java/com/netflix/hystrix/contrib/javanica/command/closure/AbstractClosureFactory.java#L47-L83","documentation":"Javanica supports defining a command inline via a closure-like anonymous class returned from a @HystrixCommand-adjacent method; AbstractClosureFactory.createClosure verifies the anonymous object implements/extends the expected closure command type (e.g. HystrixCommand or HystrixObservableCommand) before reflecting out its run()/construct() method (INVOKE_METHOD). If the object's type does not match getClosureCommandType(), a RuntimeException with the formatted ERROR_TYPE_MESSAGE ('return type of ... method should be ...') is thrown, naming the outer method and the required type.","triggerScenarios":"Returning an anonymous class from a closure-style method that is not a subclass of the expected Hystrix command type — e.g. returning `new HystrixObservableCommand<String>(...) {...}` where the factory expects HystrixCommand, or returning an arbitrary Callable/Object.","commonSituations":"Refactoring a closure command from sync to observable (or vice versa) without changing the enclosing method's declared return type; mixing closure-style and annotation-style usage; upgrading Javanica versions where closure support semantics tightened.","solutions":["Read the message: it names the outer method and the exact class the closure must extend/implement","Make the anonymous class returned from that method extend the required type (HystrixCommand for sync/async, HystrixObservableCommand for observable)","Ensure the anonymous class overrides the required method (run() or construct())","If you did not intend closure-style commands, switch to plain annotation style and remove the anonymous class return"],"exampleFix":"// before\npublic Object getUserClosure() {\n    return new Callable<User>() { public User call() { ... } };\n}\n\n// after\npublic HystrixCommand<User> getUserClosure() {\n    return new HystrixCommand<User>(setter) { protected User run() { ... } };\n}","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"boolean isValidClosure(Object closureObj, Class<?> expected) {\n    return closureObj != null && expected.isAssignableFrom(closureObj.getClass());\n}\n// before returning: if (!isValidClosure(obj, HystrixCommand.class)) throw new IllegalStateException(\"closure must be HystrixCommand\");","tryCatchPattern":"catch (RuntimeException e) { if (e.getMessage().contains(\"should be\")) throw new IllegalStateException(\"Closure signature error — check outer method return type\", e); throw e; }","preventionTips":["Declare the closure-factory method's return type as the exact command class (HystrixCommand<T>/HystrixObservableCommand<T>) so the compiler catches mismatches","Avoid closure-style commands unless required; prefer plain annotation style","Add a unit test per closure method returning the built command"],"tags":["hystrix","javanica","closure","reflection","type-mismatch"],"backgroundTag":null,"analyzedSha":"5ce3bc58c38e7ca60ef2fe0e516e390e294ad941","analyzedAt":"2026-08-14T10:55:35.600Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}