-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Description
Spring Kafka version
3.3.5
TL;DR;
Clarify Handling Exceptions and mention that only RuntimeException will be handled. Throwing something that inherits from Error, like what happens if you use Kotlins TODO() helper, will cause the consumer to exit and close.
Problem:
The Handling Exceptions > DefaultErrorHandler documentation says:
The DefaultErrorHandler considers certain exceptions to be fatal, and retries are skipped for such exceptions; the recoverer is invoked on the first failure. The exceptions that are considered fatal, by default, are:
DeserializationException MessageConversionException ConversionException MethodArgumentResolutionException NoSuchMethodException ClassCastException
That is correct but also a bit misleading. 😅 DefaultErrorHandler will indeed treat those as fatal, non-recoverable, exceptions but the catch statement in KafkaMessageListenerContainer means only throwable that inherits from RuntimeException will reach the error handler and be handled gracefully.
Line 2781 in bb6280c
| catch (RuntimeException e) { |
If the code throws something inheriting from Error, like the TODO() kotlin helper that the Intellij IDE uses for on auto-generated method stubs do, then we will end up in the outer Error e handler which will cause the consumer loop to shutdown leading to a application that is "alive" according to Spring Boot Actuator yet have a closed Kafka consumer.
Lines 1380 to 1385 in bb6280c
| catch (Error e) { // NOSONAR - rethrown | |
| this.logger.error(e, "Stopping container due to an Error"); | |
| this.fatalError = true; | |
| wrapUp(e); | |
| throw e; | |
| } |
Context
A IDE generate method stub that used the TODO() kotlin function ended up in production. Since it inherits from Error and not from RuntimeException we ended up with a spring boot app that reported Status: OK but had a dead kafka consumer.