KIP-800 — Join/leave reason strings
Status: implemented — back to the KIP index.
What the KIP changes in Apache Kafka
Kafka 3.1 added a nullable reason string to JoinGroup requests (v8) and
to each member entry in LeaveGroup requests (v5), so clients can tell the
broker why they are rejoining or leaving ("the consumer is being
closed", rebalance triggered by metadata change, …). It is a
request-side-only, diagnostics-oriented field: Apache logs it to make
rebalance storms explainable.
How kaas implements it
crates/kaas-codec/src/api/join_group.rsdecodes the nullablereasonon v8+ requests (kaas serves JoinGroup v2–v9, flexible from v6);crates/kaas-codec/src/api/leave_group.rsdecodes the per-memberreasonon v5+ (kaas serves v0–v5, flexible from v4). Both are version-gated exactly per the Apache 3.7 schema — v7/v4 wire bytes must not contain the field, and the encoders enforce that.- This field earned its regression fixture the hard way: the pre-fix v5
LeaveGroup decoder read the reason's length byte as the tagged-field
count, which broke every modern Java client's clean shutdown (the
consumer sends "the consumer is being closed" on close). The fixture
test in
leave_group.rspins the literal bytes a Java 3.7 client sends. - The broker decodes the reason and then discards it. Neither handler
(
crates/kaas-broker/src/handlers/join_group.rs,leave_group.rs) nor the group coordinator (crates/kaas-coordinator/src/group.rs) logs, stores, or acts on it — there is no occurrence of the field beyond the codec layer. Wire parity is what "implemented" means here; surfacing the reason in broker logs/metrics, which is the KIP's operational payoff, is honest follow-up work.
Since clients enable this unconditionally at v8/v5, the load-bearing part is accepting the field without corrupting the rest of the request — which is exactly where the old bug lived.
How it's verified
crates/kaas-codec/src/api/leave_group.rs:v5_java_client_fixture_with_reason(captured Java-client bytes, reason "bye", nullgroup_instance_id) andv4_omits_reason_on_the_wire(the field must not leak into v4 encodings).crates/kaas-codec/src/api/join_group.rs:v8_adds_reasonround-trips the field at v8+.scripts/kafka-consumer-groups.shandscripts/kafka-console-consumer.shrun modern Java clients through full join → consume → clean-close cycles, which send reason strings on every leave.
See also the JoinGroup and LeaveGroup entries in the per-API reference.