{"record":{"id":"127169af8f1266fa","repo":"Netflix/Hystrix","slug":"method-with-name-doesn-t-exist-in-class","errorCode":null,"errorMessage":"method with name '{}' doesn't exist in class '{}'","messagePattern":"method with name '(.+?)' doesn't exist in class '(.+?)'","errorType":"validation","errorClass":"HystrixCachingException","httpStatus":null,"severity":"error","filePath":"hystrix-contrib/hystrix-javanica/src/main/java/com/netflix/hystrix/contrib/javanica/cache/CacheInvocationContextFactory.java","lineNumber":74,"sourceCode":"     * @return initialized and configured {@link CacheInvocationContext}\n     */\n    public static CacheInvocationContext<CacheRemove> createCacheRemoveInvocationContext(MetaHolder metaHolder) {\n        Method method = metaHolder.getMethod();\n        if (method.isAnnotationPresent(CacheRemove.class)) {\n            CacheRemove cacheRemove = method.getAnnotation(CacheRemove.class);\n            MethodExecutionAction cacheKeyMethod = createCacheKeyAction(cacheRemove.cacheKeyMethod(), metaHolder);\n            return new CacheInvocationContext<CacheRemove>(cacheRemove, cacheKeyMethod, metaHolder.getObj(), method, metaHolder.getArgs());\n        }\n        return null;\n    }\n\n    private static MethodExecutionAction createCacheKeyAction(String method, MetaHolder metaHolder) {\n        MethodExecutionAction cacheKeyAction = null;\n        if (StringUtils.isNotBlank(method)) {\n            Method cacheKeyMethod = getDeclaredMethod(metaHolder.getObj().getClass(), method,\n                    metaHolder.getMethod().getParameterTypes());\n            if (cacheKeyMethod == null) {\n                throw new HystrixCachingException(\"method with name '\" + method + \"' doesn't exist in class '\"\n                        + metaHolder.getObj().getClass() + \"'\");\n            }\n            if (!cacheKeyMethod.getReturnType().equals(String.class)) {\n                throw new HystrixCachingException(\"return type of cacheKey method must be String. Method: '\" + method + \"', Class: '\"\n                        + metaHolder.getObj().getClass() + \"'\");\n            }\n\n            MetaHolder cMetaHolder = MetaHolder.builder().obj(metaHolder.getObj()).method(cacheKeyMethod).args(metaHolder.getArgs()).build();\n            cacheKeyAction = new MethodExecutionAction(cMetaHolder.getObj(), cacheKeyMethod, cMetaHolder.getArgs(), cMetaHolder);\n        }\n        return cacheKeyAction;\n    }\n\n}\n","sourceCodeStart":56,"sourceCodeEnd":89,"githubUrl":"https://github.com/Netflix/Hystrix/blob/5ce3bc58c38e7ca60ef2fe0e516e390e294ad941/hystrix-contrib/hystrix-javanica/src/main/java/com/netflix/hystrix/contrib/javanica/cache/CacheInvocationContextFactory.java#L56-L89","documentation":"With @CacheRemove/@CacheResult caching, you can point to a cacheKeyMethod that computes the cache key. Javanica looks it up on the target class with getDeclaredMethod(clazz, method, <same parameter types as the annotated method>) and throws HystrixCachingException when nothing matches. Both the name and the exact parameter-type list must line up with the annotated method.","triggerScenarios":"@CacheRemove(cacheKeyMethod = \"keyFor\") where keyFor does not exist, is misspelled, is declared in a superclass (getDeclaredMethod only sees the class itself), or takes different parameter types than the annotated method (extra/missing params, int vs Integer).","commonSituations":"Renaming the key method; refactoring the annotated method's parameters without updating the key method's signature; key method overloaded so reflection picks nothing exact.","solutions":["Declare a method with the exact name given in cacheKeyMethod that takes the same parameter types as the annotated method and returns String.","Check spelling and case of cacheKeyMethod.","If the key needs fewer inputs, keep the same parameter list anyway and ignore unneeded arguments, or build the key inline via @CacheKey on parameters instead."],"exampleFix":"// before\n@CacheRemove(commandKey = \"getUser\", cacheKeyMethod = \"userKey\")\npublic void updateUser(User u) { ... }\nprivate String userKey(Long id) { ... }  // wrong params\n\n// after\n@CacheRemove(commandKey = \"getUser\", cacheKeyMethod = \"userKey\")\npublic void updateUser(User u) { ... }\nprivate String userKey(User u) { return u.getId(); }","handlingStrategy":"validation","validationCode":"static void assertCacheKeyMethodExists(Object target, Method annotated, String keyMethodName) {\n    if (keyMethodName == null || keyMethodName.trim().isEmpty()) return;\n    Method found = null;\n    try { found = target.getClass().getDeclaredMethod(keyMethodName, annotated.getParameterTypes()); } catch (NoSuchMethodException ignored) { }\n    if (found == null) throw new IllegalStateException(\"cacheKeyMethod '\" + keyMethodName + \"' with matching params not found on \" + target.getClass());\n}","typeGuard":null,"tryCatchPattern":"try { ... } catch (HystrixCachingException e) { if (e.getMessage().contains(\"doesn't exist\")) { fail fast with class+method names; } rethrow; } — config defect, never recoverable at runtime.","preventionTips":["Keep cache key methods directly on the annotated class (not superclass/interface) with identical parameter lists.","Prefer @CacheKey parameter annotations over cacheKeyMethod when signatures drift often."],"tags":["hystrix","javanica","cache","cache-key","reflection"],"backgroundTag":null,"analyzedSha":"5ce3bc58c38e7ca60ef2fe0e516e390e294ad941","analyzedAt":"2026-08-14T10:55:35.600Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}