You are viewing a plain text version of this content. The canonical link for it is here.
Posted to jira@kafka.apache.org by "Eric Chang (Jira)" <ji...@apache.org> on 2026/07/14 09:59:00 UTC
[jira] [Created] (KAFKA-20802) ClusterTestExtensions#afterEach throws NPE when a detected thread terminates before the leak report is built
Eric Chang created KAFKA-20802:
----------------------------------
Summary: ClusterTestExtensions#afterEach throws NPE when a detected thread terminates before the leak report is built
Key: KAFKA-20802
URL: https://issues.apache.org/jira/browse/KAFKA-20802
Project: Kafka
Issue Type: Bug
Reporter: Eric Chang
Assignee: Eric Chang
{{ClusterTestExtensions#afterEach}} builds the thread-leak error message with {{t.getThreadGroup().getName()}}. {{Thread#getThreadGroup()}} returns null after a thread has terminated.
If a thread returned by {{DetectThreadLeak#newThreads()}} terminates between the snapshot and message formatting, {{afterEach}} throws an NPE and fails the test even though the thread is no longer a leak.
h3. CI evidence
* Full job: https://github.com/apache/kafka/actions/runs/29228499012/job/86748625389
* NPE in the JUnit test step: https://github.com/apache/kafka/actions/runs/29228499012/job/86748625389#step:6:136310
* Flaky-test report: https://github.com/apache/kafka/actions/runs/29228499012/job/86748625389#step:10:1872
* Affected test: {{MetadataQuorumCommandTest.testDescribeQuorumStatusSuccessful [5]}}
{code}
java.lang.NullPointerException: Cannot invoke "java.lang.ThreadGroup.getName()" because the return value of "java.lang.Thread.getThreadGroup()" is null
at org.apache.kafka.common.test.junit.ClusterTestExtensions.lambda$afterEach$2(ClusterTestExtensions.java:188)
{code}
h3. Reproduction
A deterministic regression test can reproduce the same NPE by making {{DetectThreadLeak#newThreads()}} return a thread that has already been joined, then invoking the real {{afterEach}} path. The proposed logic passes this regression test and continues to report live leaked threads.
I also ran the actual affected test locally for 120 isolated cluster contexts using Java 17, 4 forks, and retries disabled. All 120 passed, so the natural timing window did not reproduce locally in that batch.
h3. Expected behavior
Threads that have already terminated should be ignored while constructing the leak report because they are not leaks. The reporting path must not throw an NPE.
h3. Related issue
KAFKA-17189 (https://issues.apache.org/jira/browse/KAFKA-17189) describes the underlying snapshot-to-report race and proposes adding {{Thread::isAlive}} to the leak-detector filter. This issue tracks the concrete {{ClusterTestExtensions#afterEach}} NPE observed in CI.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)