{"record":{"id":"bc76ade6ff3baefa","repo":"spring-projects/spring-framework","slug":"service-locator-exception-exceptionclass-getnam","errorCode":null,"errorMessage":"Service locator exception [${exceptionClass.getName()}] neither has a (String, Throwable) constructor nor a (String) constructor","messagePattern":"Service locator exception \\[(.+?)\\] neither has a \\(String, Throwable\\) constructor nor a \\(String\\) constructor","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"spring-beans/src/main/java/org/springframework/beans/factory/config/ServiceLocatorFactoryBean.java","lineNumber":294,"sourceCode":"\t * @param exceptionClass the exception class\n\t * @return the constructor to use\n\t * @see #setServiceLocatorExceptionClass\n\t */\n\t@SuppressWarnings(\"unchecked\")\n\tprotected Constructor<Exception> determineServiceLocatorExceptionConstructor(Class<? extends Exception> exceptionClass) {\n\t\ttry {\n\t\t\treturn (Constructor<Exception>) exceptionClass.getConstructor(String.class, Throwable.class);\n\t\t}\n\t\tcatch (NoSuchMethodException ex) {\n\t\t\ttry {\n\t\t\t\treturn (Constructor<Exception>) exceptionClass.getConstructor(Throwable.class);\n\t\t\t}\n\t\t\tcatch (NoSuchMethodException ex2) {\n\t\t\t\ttry {\n\t\t\t\t\treturn (Constructor<Exception>) exceptionClass.getConstructor(String.class);\n\t\t\t\t}\n\t\t\t\tcatch (NoSuchMethodException ex3) {\n\t\t\t\t\tthrow new IllegalArgumentException(\n\t\t\t\t\t\t\t\"Service locator exception [\" + exceptionClass.getName() +\n\t\t\t\t\t\t\t\"] neither has a (String, Throwable) constructor nor a (String) constructor\");\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Create a service locator exception for the given cause.\n\t * Only called in case of a custom service locator exception.\n\t * <p>The default implementation can handle all variations of\n\t * message and exception arguments.\n\t * @param exceptionConstructor the constructor to use\n\t * @param cause the cause of the service lookup failure\n\t * @return the service locator exception to throw\n\t * @see #setServiceLocatorExceptionClass\n\t */\n\tprotected Exception createServiceLocatorException(Constructor<Exception> exceptionConstructor, BeansException cause) {","sourceCodeStart":276,"sourceCodeEnd":312,"githubUrl":"https://github.com/spring-projects/spring-framework/blob/69bf83ad716d0cfc4b0520a19b4d8b24c79d1538/spring-beans/src/main/java/org/springframework/beans/factory/config/ServiceLocatorFactoryBean.java#L276-L312","documentation":"Thrown by ServiceLocatorFactoryBean.determineServiceLocatorExceptionConstructor() when the custom exception class set via setServiceLocatorExceptionClass does not expose any of the supported constructors: (String, Throwable), (Throwable), or (String). ServiceLocatorFactoryBean needs to wrap lookup failures (NoSuchBeanDefinitionException etc.) into the user's exception type, and it can only do so reflectively if such a constructor exists. The error message lists the exception class name that failed the check.","triggerScenarios":"Calling setServiceLocatorExceptionClass(MyException.class) where MyException has only a no-arg or (int) constructor. Providing an exception class with private/package-private constructors that reflection cannot reach. Passing a checked exception whose constructors don't match the supported signatures.","commonSituations":"Custom business exception without the conventional message/cause constructors. Refactoring the exception class and removing the (String, Throwable) constructor. Using a library exception class whose API differs.","solutions":["Add a public constructor to your exception class with one of: (String, Throwable), (Throwable), or (String). The (String, Throwable) form is preferred so both message and cause propagate.","If you cannot change the exception class, wrap it in a custom subclass that adds such a constructor, or stop using setServiceLocatorExceptionClass and let Spring throw its own BeansException subclasses.","Ensure the constructor is public so reflection (Class.getConstructor) can find it."],"exampleFix":"// before (broken)\npublic class MyException extends RuntimeException {\n  public MyException(int code) { ... }\n}\nfb.setServiceLocatorExceptionClass(MyException.class); // throws\n// after\npublic class MyException extends RuntimeException {\n  public MyException(String msg, Throwable cause) { super(msg, cause); }\n  public MyException(String msg) { super(msg); }\n}","handlingStrategy":"type-guard","validationCode":"Class<? extends Exception> c = MyException.class;\nboolean hasCtor =\n    hasPublicCtor(c, String.class, Throwable.class) ||\n    hasPublicCtor(c, Throwable.class) ||\n    hasPublicCtor(c, String.class);\nif (!hasCtor) {\n    throw new IllegalStateException(c.getName() + \" needs a (String,Throwable)/(Throwable)/(String) constructor\");\n}\nfb.setServiceLocatorExceptionClass(c);","typeGuard":"static boolean hasSupportedLocatorExceptionCtor(Class<? extends Exception> c) {\n    try { c.getConstructor(String.class, Throwable.class); return true; }\n    catch (NoSuchMethodException ignore) {}\n    try { c.getConstructor(Throwable.class); return true; }\n    catch (NoSuchMethodException ignore) {}\n    try { c.getConstructor(String.class); return true; }\n    catch (NoSuchMethodException ignore) {}\n    return false;\n}","tryCatchPattern":"try {\n    fb.setServiceLocatorExceptionClass(MyException.class);\n} catch (IllegalArgumentException ex) {\n    if (ex.getMessage().contains(\"neither has a\")) {\n        // add a (String, Throwable) constructor to MyException, then retry\n    }\n    throw ex;\n}","preventionTips":["Give every custom service-locator exception at least a public (String, Throwable) constructor.","Write a unit test asserting the exception class has a supported constructor.","If you cannot modify the class, do not set serviceLocatorExceptionClass and accept Spring's default BeansException."],"tags":["spring","factory-bean","service-locator","reflection","exception-design"],"backgroundTag":null,"analyzedSha":"69bf83ad716d0cfc4b0520a19b4d8b24c79d1538","analyzedAt":"2026-08-09T15:32:58.770Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}