{"id":"3768a31f8fa58bb2","repo":"spring-projects/spring-framework","slug":"no-executor-specified-and-no-default-executor-set","errorCode":null,"errorMessage":"No executor specified and no default executor set on AsyncExecutionInterceptor either","messagePattern":"No executor specified and no default executor set on AsyncExecutionInterceptor either","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"spring-aop/src/main/java/org/springframework/aop/interceptor/AsyncExecutionInterceptor.java","lineNumber":106,"sourceCode":"\t\tsuper(defaultExecutor, exceptionHandler);\n\t}\n\n\n\t/**\n\t * Intercept the given method invocation, submit the actual calling of the method to\n\t * the correct task executor and return immediately to the caller.\n\t * @param invocation the method to intercept and make asynchronous\n\t * @return {@link Future} if the original method returns {@code Future}; {@code null}\n\t * otherwise.\n\t */\n\t@Override\n\tpublic @Nullable Object invoke(final MethodInvocation invocation) throws Throwable {\n\t\tClass<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);\n\t\tfinal Method userMethod = BridgeMethodResolver.getMostSpecificMethod(invocation.getMethod(), targetClass);\n\n\t\tAsyncTaskExecutor executor = determineAsyncExecutor(userMethod);\n\t\tif (executor == null) {\n\t\t\tthrow new IllegalStateException(\n\t\t\t\t\t\"No executor specified and no default executor set on AsyncExecutionInterceptor either\");\n\t\t}\n\n\t\tCallable<Object> task = () -> {\n\t\t\ttry {\n\t\t\t\tObject result = invocation.proceed();\n\t\t\t\tif (result instanceof Future<?> future) {\n\t\t\t\t\treturn future.get();\n\t\t\t\t}\n\t\t\t}\n\t\t\tcatch (ExecutionException ex) {\n\t\t\t\tThrowable cause = ex.getCause();\n\t\t\t\thandleError(cause == null ? ex : cause, userMethod, invocation.getArguments());\n\t\t\t}\n\t\t\tcatch (Throwable ex) {\n\t\t\t\thandleError(ex, userMethod, invocation.getArguments());\n\t\t\t}\n\t\t\treturn null;","sourceCodeStart":88,"sourceCodeEnd":124,"githubUrl":"https://github.com/spring-projects/spring-framework/blob/e8729d043887bf0d0baf91e062e909b56eb2b708/spring-aop/src/main/java/org/springframework/aop/interceptor/AsyncExecutionInterceptor.java#L88-L124","documentation":"Thrown by AsyncExecutionInterceptor.invoke when determineAsyncExecutor returns null: no qualifier was set, no explicit executor was supplied, and getDefaultExecutor resolved to null. AsyncExecutionInterceptor normally falls back to a SimpleAsyncTaskExecutor, so reaching this branch means a custom subclass overrode getDefaultExecutor to return null, or the executor was explicitly cleared.","triggerScenarios":"A subclass of AsyncExecutionAspectSupport overrides getDefaultExecutor to return null (instead of falling back) and no executor was passed via constructor/setExecutor; or setExecutor(null) was called and the supplier yields null.","commonSituations":"Custom async aspect that tries to fail-fast when no TaskExecutor bean is present; programmatic AOP wiring that forgets to provide an Executor; disabling the SimpleAsyncTaskExecutor fallback.","solutions":["Define a TaskExecutor bean (optionally named 'taskExecutor') in the ApplicationContext so getDefaultExecutor resolves it.","Pass a concrete Executor to the constructor or call setExecutor(executor) on the interceptor.","If subclassing, keep AsyncExecutionInterceptor's SimpleAsyncTaskExecutor fallback rather than returning null from getDefaultExecutor."],"exampleFix":"// before\n@Override\nprotected Executor getDefaultExecutor(BeanFactory bf) {\n    return null; // fail-fast -> error 102\n}\n\n// after\n@Override\nprotected Executor getDefaultExecutor(BeanFactory bf) {\n    Executor e = super.getDefaultExecutor(bf);\n    return (e != null ? e : new SimpleAsyncTaskExecutor());\n}","handlingStrategy":"validation","validationCode":"Executor ex = interceptor.determineAsyncExecutor(method); // or resolve eagerly\nif (ex == null) {\n    ex = new SimpleAsyncTaskExecutor();\n    interceptor.setExecutor(ex);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always define a TaskExecutor bean (named 'taskExecutor' if multiple exist).","Pass a concrete Executor when constructing interceptors programmatically.","Do not override getDefaultExecutor to return null without supplying an alternative."],"tags":["spring-aop","async","executor","configuration"],"analyzedSha":"e8729d043887bf0d0baf91e062e909b56eb2b708","analyzedAt":"2026-08-04T19:07:39.725Z","schemaVersion":2}