You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@kafka.apache.org by "Tamas Kornai (Jira)" <ji...@apache.org> on 2026/08/04 11:57:00 UTC
[jira] [Created] (KAFKA-20890) KRaft broker startup can fail to restore persisted dynamic broker configs when the local metadata snapshot is missing or stale
Tamas Kornai created KAFKA-20890:
------------------------------------
Summary: KRaft broker startup can fail to restore persisted dynamic broker configs when the local metadata snapshot is missing or stale
Key: KAFKA-20890
URL: https://issues.apache.org/jira/browse/KAFKA-20890
Project: Kafka
Issue Type: Bug
Components: config, core, kraft
Affects Versions: 4.3.0, 4.2.0, 4.1.0, 4.0.0, 3.9.2
Reporter: Tamas Kornai
On KRaft broker startup, persisted dynamic broker configurations may not be available when runtime components and their Reconfigurable implementations are initialized. When the latest local metadata snapshot is missing or does not yet contain the relevant ConfigRecord, the broker starts from its static configuration and receives the persisted dynamic configuration later through metadata-log replay.
That replay is processed as a live reconfiguration. A configuration whose final persisted value is valid can therefore be rejected by validation that compares the requested value with the component's current runtime state. The broker remains on its static value even though the dynamic configuration store, and consequently DescribeConfigs, can report the persisted dynamic value.
This was originally observed with num.recovery.threads.per.data.dir, but the underlying problem is not specific to recovery-thread configuration. It can affect dynamic configurations whose validation depends on current runtime state, initialization order, or another dynamically supplied setting.
## Concrete production observation
The static broker value was:
num.recovery.threads.per.data.dir=1
A cluster-default dynamic configuration was rolled out in two safe steps:
unset -> 2 -> 4
The original rollout succeeded. Brokers logged both runtime transitions:
Resizing recovery thread pool size for each data dir from 1 to 2
Resizing recovery thread pool size for each data dir from 2 to 4
During a subsequent ZooKeeper-to-KRaft transition, affected brokers rebuilt their configuration as:
1 -> 4 -> 1
Their final runtime KafkaConfig value was 1, while the stored cluster-default dynamic configuration continued to report 4 and there were no per-broker overrides.
Later attempts to apply 4 were rejected because the active runtime value was still 1:
Dynamic thread count update validation failed for num.recovery.threads.per.data.dir=4,
value should not be greater than double the current value 1
## Expected behavior
* A broker restart restores the final persisted dynamic configuration before dependent runtime components become active, regardless of whether the latest local metadata snapshot happens to contain that configuration.
* - Startup restoration is not rejected merely because the persisted final value is more than a live-update limit away from the static value.
* - If applying a dynamic configuration fails, configuration APIs do not report that rejected value as the broker's effective configuration.
## Actual behavior
* Without a suitable local snapshot, the broker initializes affected components using the static value.
* - Metadata-log replay later presents the persisted value as a live update.
* - Current-state-dependent validation can reject that update.
* - The component remains on the static runtime value.
* - The dynamic configuration cache can nevertheless contain and report the rejected persisted value, so the reported effective configuration differs from the active runtime state.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)