Kafka binder health-check consumer failures return DOWN without logging the exception
维护者通常 1 天内回复
评估
- 难度
- 2/5
- 预计耗时
- 1-3 小时
- 新手友好度
- 25/100
- Issue 类型
- 缺陷
- 描述清晰度
- 描述清楚
- 活跃度
- 停滞
- 技术栈
- java, kafka, spring-boot
- 领域
- backend, observability
调研方向
Start with AbstractKafkaBinderHealthIndicator.buildTopicsHealth() and safelyBuildTopicsHealth() in the Kafka binder core; the issue identifies both as paths that convert failures into health results without logging. Read the existing logging conventions for health indicator failures, then check that the returned health status remains DOWN and the underlying exception is logged without repeated probe failures flooding logs.
由索引模型根据 Issue 内容生成。
描述
Describe the issue
The Kafka binder can report DOWN because its health-check metadata consumer cannot be constructed, without logging the failure or its underlying cause. Meanwhile, application startup and the actual listener containers can succeed.
The health endpoint exposes only:
org.apache.kafka.common.KafkaException: Failed to construct kafka consumer
In the case we investigated, the underlying exception was:
java.lang.IllegalStateException: No delegate deserializer configured
This report is about missing error logging, not about accepting an incomplete deserializer configuration. Returning DOWN is appropriate, but the diagnostic cause should also be available in the application logs.
To Reproduce
The following is a reduced configuration illustrating the triggering setup: use ErrorHandlingDeserializer at binder scope and configure its value delegate only at binding scope.
-
Start a Spring Boot application with Actuator, the web starter, the Spring Cloud Stream Kafka binder, and a reachable plaintext Kafka broker.
-
Register a simple function:
@Bean public Consumer<String> consume() { return value -> {}; } -
Configure the binder and binding:
management: endpoint: health: show-details: always spring: cloud: function: definition: consume stream: bindings: consume-in-0: destination: health-repro group: health-repro consumer: useNativeDecoding: true kafka: binder: brokers: localhost:9092 consumer-properties: key.deserializer: org.springframework.kafka.support.serializer.ErrorHandlingDeserializer value.deserializer: org.springframework.kafka.support.serializer.ErrorHandlingDeserializer spring.deserializer.key.delegate.class: org.apache.kafka.common.serialization.StringDeserializer bindings: consume-in-0: consumer: configuration: spring.deserializer.value.delegate.class: org.apache.kafka.common.serialization.StringDeserializer -
Let the application start, then call
GET /actuator/health. -
Observe that binder health is
DOWNwithFailed to construct kafka consumer, despite the listener container running. No corresponding health-check exception or nested cause is logged at WARN/ERROR.
The failure was reproduced in a multi-binder application and an HTTP integration test. The reduced single-binder example above is provided to illustrate the configuration pattern; it has not been run as a separate sample project.
Version of the framework
- Spring Boot: 4.1.2
- Spring Cloud release train: 2025.1.4
- Spring Cloud Stream: 5.0.4
- Spring Cloud Stream Kafka binder and Kafka binder core: 5.0.4
- Spring for Apache Kafka (
spring-kafka): 4.1.2 - Apache Kafka clients: 4.2.2
- Java: Eclipse Temurin 25.0.5
The Spring Boot, Spring Cloud, and Java settings were checked against the application build configuration. The packaged application JAR confirms the resolved Spring Boot, Spring Cloud Stream, Spring Kafka, and Kafka client versions. The failing HTTP integration test ran on Java 25.0.5. The exception-to-health-result handling was also checked in the released v5.0.4 source and on the main branch.
Expected behavior
When metadata consumer construction fails, log an ERROR identifying the Kafka binder health check and include the exception and full cause chain. If WARN is the project's convention for health-indicator failures, that would still be substantially more actionable than the current silent conversion.
The health endpoint should continue returning DOWN; startup need not fail solely because of a lazily created health-check consumer. Logging is expected when the health check actually encounters the failure, not necessarily during startup.
Please consider logging on the initial failure/state transition or otherwise deduplicating/rate-limiting repeated failures, so regular health probes do not flood logs with identical stack traces. There is no need to log configuration maps or credentials.
Additional context
The relevant code paths appear to be:
KafkaBinderHealthIndicatorConfiguration.kafkaBinderHealthIndicator(): starts with byte-array deserializers, then merges binder consumer configuration over them. Binding-specific delegate settings are not included.AbstractKafkaBinderHealthIndicator.buildTopicsHealth(): catches the exception and returnsHealth.down(ex).build()without logging it.AbstractKafkaBinderHealthIndicator.safelyBuildTopicsHealth(): also converts execution failures into a health result without logging.
Because the exception is handled inside the indicator, the exception-logging path in the superclass is not reached. Health details retain the outer exception message rather than the useful nested deserializer error.
Supplying spring.deserializer.value.delegate.class at binder scope resolves this particular configuration failure, while bindings can still override the delegate as needed. However, that workaround does not address the missing diagnostics for this or other health-check failures.
I searched existing open issues for the exact error, missing delegates, the health indicator class, and health-check logging. Related but apparently different reports include spring-cloud/spring-cloud-stream#2958 (binary compatibility), spring-cloud/spring-cloud-stream#3042 (custom multi-binder indicators), and spring-cloud/spring-cloud-stream#3138 (Kafka Streams/DNS connectivity).
- 主要语言
- Java
- 星标
- 1.1k
- 派生
- 653
- 平均合并
- 2 天 15 小时
- 30 天内合并 PR
- 8
环境准备
这个项目没有提供开发容器、Dockerfile 或贡献指南,环境需要你自己搭建:先看它的 README,通用步骤见我们的新手贡献指南。
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
spring-cloud/spring-cloud-stream 的其他 Issue
-
Deadlock between `KafkaBinderMetrics.close()` and the offset-lag task on context shutdown可能已有人在做 @caiocv18 于 3 天前认领。 未关闭
难度 4/5 3-5 天 新手友好度 55/100
spring-cloud/spring-cloud-stream#3332 · 1 条评论 ·
维护者通常 1 天内回复
-
Kafka pollable consumers lose ConsumerFactory listeners when max.poll.records is greater than one未关闭
难度 4/5 3-5 天 新手友好度 55/100
spring-cloud/spring-cloud-stream#3324 · 2 条评论 ·
维护者通常 1 天内回复
-
DefaultPollableMessageSource: invoke afterSendCompletion for already-applied interceptors when a message is discarded可能已有人在做 @ferblaca 于 3 天前认领。 未关闭
难度 3/5 1-2 天 新手友好度 74/100
spring-cloud/spring-cloud-stream#3316 ·
维护者通常 1 天内回复
-
StreamBridge removing BindingProperties leads to wrong destination in ProvisioningProvider可能重新可做 @olegz 于 63 天前认领,目前没有进行中的 PR。 未关闭bug
spring-cloud/spring-cloud-stream#3257 · 6 条评论 · 2 个 reaction · 已指派 1 人 ·
维护者通常 1 天内回复
-
StreamBridge's hashProducerProperties produces hash collisions across different binding names, causing Partition key cannot be null可能重新可做 关联的 PR 已关闭且未合并。 未关闭
难度 4/5 3-5 天 新手友好度 48/100
spring-cloud/spring-cloud-stream#3242 · 2 条评论 ·
维护者通常 1 天内回复
查看 spring-cloud/spring-cloud-stream 的全部 Issue
相似的 Issue
-
type: dependency-upgrade
难度 2/5 1-3 小时 新手友好度 61/100
spring-projects/spring-graphql#1556 ·
-
hermes-queue
难度 1/5 1 小时以内 新手友好度 91/100
chrisalunlloyd2-sudo/mindpalace#373 ·
维护者通常 1 天内回复
-
难度 2/5 1-3 小时 新手友好度 76/100
维护者通常 1 天内回复
-
bug priority: lowest
难度 2/5 1-3 小时 新手友好度 62/100
SkriptLang/Skript#8953 · 1 条评论 ·
维护者通常 1 天内回复
-
quality-assurance
难度 2/5 1-3 小时 新手友好度 62/100
Paul-Austin-Oswego-CSC480-HCI521/gift-app#228 ·
维护者通常 1 天内回复