spring-projects / spring-projects/spring-framework
@Async event listener suspending function throws IllegalArgumentException
@sdeleuze is already working on this.
Since Jan 29, 2026.
- Dominant language
- Java
- Stars
- 60.2k
- Forks
- 38.8k
- Avg merge
- 5d 2h
- Merged PRs (30d)
- 27
Description
Spring Framework 7.0.3
Java 17
Kotlin 2.2.21 (Coroutines 1.10.2)
While asynchronously handling an event, a suspending function throws IllegalArgumentException as follows:
java.lang.IllegalArgumentException: Invalid return type for async method (only Future and void supported): class java.lang.Object
at org.springframework.aop.interceptor.AsyncExecutionAspectSupport.doSubmit(AsyncExecutionAspectSupport.java:290) ~[spring-aop-7.0.3.jar:7.0.3]
at org.springframework.aop.interceptor.AsyncExecutionInterceptor.invoke(AsyncExecutionInterceptor.java:127) ~[spring-aop-7.0.3.jar:7.0.3]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-7.0.3.jar:7.0.3]
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:719) ~[spring-aop-7.0.3.jar:7.0.3]
at com.example.demo.EventHandler$$SpringCGLIB$$0.handleCustomEventFail(<generated>) ~[classes/:na]
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:565) ~[na:na]
The event listener function:
@Async
@EventListener
suspend fun handleCustomEventFail(customSpringEvent: CustomSpringEvent) {
println("[suspend] Handling ${customSpringEvent.id} event")
}
A similar event listener non-suspending function works just fine:
@Async
@EventListener
fun handleCustomEventSuccess(customSpringEvent: CustomSpringEvent) {
println("[non-suspend] Handling ${customSpringEvent.id} event")
}
A minimal reproducible example is available at https://github.com/joaodias14/demo-async.
We can workaround it by using a coroutine builder function, such as CoroutineScope.launch(), to explicitly start a coroutine, but it would be great if @Async works seamlessly with suspending functions.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.