Skip to main content

kafka_conn/
error_code.rs

1//! The broker error-code table.
2//!
3//! One table, one file — the M5 artifact. It is *derived* from
4//! `kafka_protocol::ResponseError` rather than transcribed from it, and that
5//! is the load-bearing part:
6//!
7//! * `retriable()` delegates to the crate's `is_retriable()`, which encodes
8//!   what the protocol says rather than what we remember it saying.
9//! * [`ErrorCode::from_response_error`] matches `ResponseError` exhaustively.
10//!   `ResponseError` is a plain enum, so when an upstream bump adds a code that
11//!   match stops compiling — a new error code becomes a build failure to
12//!   triage rather than a silent hole in the classification.
13//!
14//! The two axes the crate does not model — whether a code should invalidate
15//! the metadata snapshot, and whether it should invalidate a cached group or
16//! transaction coordinator — are ours, and are exhaustive matches over our own
17//! enum for the same reason.
18//!
19//! [`ErrorCode::Unknown`] is not optional. `kafka-protocol` 0.17 knows codes
20//! through Kafka 4.1; the acceptance suite runs against 4.3.1, so codes with no
21//! name here are the expected case and must round-trip and render rather than
22//! collapsing into a generic failure.
23
24use kafka_protocol::ResponseError;
25
26/// A Kafka broker error code.
27#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
28pub enum ErrorCode {
29    /// The server experienced an unexpected error when processing the request.
30    UnknownServerError,
31    /// The requested offset is not within the range of offsets maintained by the server.
32    OffsetOutOfRange,
33    /// This message has failed its CRC checksum, exceeds the valid size, has a null key for a compacted topic, or is otherwise corrupt.
34    CorruptMessage,
35    /// This server does not host this topic-partition.
36    UnknownTopicOrPartition,
37    /// The requested fetch size is invalid.
38    InvalidFetchSize,
39    /// There is no leader for this topic-partition as we are in the middle of a leadership election.
40    LeaderNotAvailable,
41    /// For requests intended only for the leader, this error indicates that the broker is not the current leader. For requests intended for any replica, this error indicates that the broker is not a replica of the topic partition.
42    NotLeaderOrFollower,
43    /// The request timed out.
44    RequestTimedOut,
45    /// The broker is not available.
46    BrokerNotAvailable,
47    /// The replica is not available for the requested topic-partition. Produce/Fetch requests and other requests intended only for the leader or follower return NOT_LEADER_OR_FOLLOWER if the broker is not a replica of the topic-partition.
48    ReplicaNotAvailable,
49    /// The request included a message larger than the max message size the server will accept.
50    MessageTooLarge,
51    /// The controller moved to another broker.
52    StaleControllerEpoch,
53    /// The metadata field of the offset request was too large.
54    OffsetMetadataTooLarge,
55    /// The server disconnected before a response was received.
56    NetworkException,
57    /// The coordinator is loading and hence can't process requests.
58    CoordinatorLoadInProgress,
59    /// The coordinator is not available.
60    CoordinatorNotAvailable,
61    /// This is not the correct coordinator.
62    NotCoordinator,
63    /// The request attempted to perform an operation on an invalid topic.
64    InvalidTopicException,
65    /// The request included message batch larger than the configured segment size on the server.
66    RecordListTooLarge,
67    /// Messages are rejected since there are fewer in-sync replicas than required.
68    NotEnoughReplicas,
69    /// Messages are written to the log, but to fewer in-sync replicas than required.
70    NotEnoughReplicasAfterAppend,
71    /// Produce request specified an invalid value for required acks.
72    InvalidRequiredAcks,
73    /// Specified group generation id is not valid.
74    IllegalGeneration,
75    /// The group member's supported protocols are incompatible with those of existing members or first group member tried to join with empty protocol type or empty protocol list.
76    InconsistentGroupProtocol,
77    /// The configured groupId is invalid.
78    InvalidGroupId,
79    /// The coordinator is not aware of this member.
80    UnknownMemberId,
81    /// The session timeout is not within the range allowed by the broker (as configured by group.min.session.timeout.ms and group.max.session.timeout.ms).
82    InvalidSessionTimeout,
83    /// The group is rebalancing, so a rejoin is needed.
84    RebalanceInProgress,
85    /// The committing offset data size is not valid.
86    InvalidCommitOffsetSize,
87    /// Topic authorization failed.
88    TopicAuthorizationFailed,
89    /// Group authorization failed.
90    GroupAuthorizationFailed,
91    /// Cluster authorization failed.
92    ClusterAuthorizationFailed,
93    /// The timestamp of the message is out of acceptable range.
94    InvalidTimestamp,
95    /// The broker does not support the requested SASL mechanism.
96    UnsupportedSaslMechanism,
97    /// Request is not valid given the current SASL state.
98    IllegalSaslState,
99    /// The version of API is not supported.
100    UnsupportedVersion,
101    /// Topic with this name already exists.
102    TopicAlreadyExists,
103    /// Number of partitions is below 1.
104    InvalidPartitions,
105    /// Replication factor is below 1 or larger than the number of available brokers.
106    InvalidReplicationFactor,
107    /// Replica assignment is invalid.
108    InvalidReplicaAssignment,
109    /// Configuration is invalid.
110    InvalidConfig,
111    /// This is not the correct controller for this cluster.
112    NotController,
113    /// This most likely occurs because of a request being malformed by the client library or the message was sent to an incompatible broker. See the broker logs for more details.
114    InvalidRequest,
115    /// The message format version on the broker does not support the request.
116    UnsupportedForMessageFormat,
117    /// Request parameters do not satisfy the configured policy.
118    PolicyViolation,
119    /// The broker received an out of order sequence number.
120    OutOfOrderSequenceNumber,
121    /// The broker received a duplicate sequence number.
122    DuplicateSequenceNumber,
123    /// Producer attempted to produce with an old epoch.
124    InvalidProducerEpoch,
125    /// The producer attempted a transactional operation in an invalid state.
126    InvalidTxnState,
127    /// The producer attempted to use a producer id which is not currently assigned to its transactional id.
128    InvalidProducerIdMapping,
129    /// The transaction timeout is larger than the maximum value allowed by the broker (as configured by transaction.max.timeout.ms).
130    InvalidTransactionTimeout,
131    /// The producer attempted to update a transaction while another concurrent operation on the same transaction was ongoing.
132    ConcurrentTransactions,
133    /// Indicates that the transaction coordinator sending a WriteTxnMarker is no longer the current coordinator for a given producer.
134    TransactionCoordinatorFenced,
135    /// Transactional Id authorization failed.
136    TransactionalIdAuthorizationFailed,
137    /// Security features are disabled.
138    SecurityDisabled,
139    /// The broker did not attempt to execute this operation. This may happen for batched RPCs where some operations in the batch failed, causing the broker to respond without trying the rest.
140    OperationNotAttempted,
141    /// Disk error when trying to access log file on the disk.
142    KafkaStorageError,
143    /// The user-specified log directory is not found in the broker config.
144    LogDirNotFound,
145    /// SASL Authentication failed.
146    SaslAuthenticationFailed,
147    /// This exception is raised by the broker if it could not locate the producer metadata associated with the producerId in question. This could happen if, for instance, the producer's records were deleted because their retention time had elapsed. Once the last records of the producerId are removed, the producer's metadata is removed from the broker, and future appends by the producer will return this exception.
148    UnknownProducerId,
149    /// A partition reassignment is in progress.
150    ReassignmentInProgress,
151    /// Delegation Token feature is not enabled.
152    DelegationTokenAuthDisabled,
153    /// Delegation Token is not found on server.
154    DelegationTokenNotFound,
155    /// Specified Principal is not valid Owner/Renewer.
156    DelegationTokenOwnerMismatch,
157    /// Delegation Token requests are not allowed on PLAINTEXT/1-way SSL channels and on delegation token authenticated channels.
158    DelegationTokenRequestNotAllowed,
159    /// Delegation Token authorization failed.
160    DelegationTokenAuthorizationFailed,
161    /// Delegation Token is expired.
162    DelegationTokenExpired,
163    /// Supplied principalType is not supported.
164    InvalidPrincipalType,
165    /// The group is not empty.
166    NonEmptyGroup,
167    /// The group id does not exist.
168    GroupIdNotFound,
169    /// The fetch session ID was not found.
170    FetchSessionIdNotFound,
171    /// The fetch session epoch is invalid.
172    InvalidFetchSessionEpoch,
173    /// There is no listener on the leader broker that matches the listener on which metadata request was processed.
174    ListenerNotFound,
175    /// Topic deletion is disabled.
176    TopicDeletionDisabled,
177    /// The leader epoch in the request is older than the epoch on the broker.
178    FencedLeaderEpoch,
179    /// The leader epoch in the request is newer than the epoch on the broker.
180    UnknownLeaderEpoch,
181    /// The requesting client does not support the compression type of given partition.
182    UnsupportedCompressionType,
183    /// Broker epoch has changed.
184    StaleBrokerEpoch,
185    /// The leader high watermark has not caught up from a recent leader election so the offsets cannot be guaranteed to be monotonically increasing.
186    OffsetNotAvailable,
187    /// The group member needs to have a valid member id before actually entering a consumer group.
188    MemberIdRequired,
189    /// The preferred leader was not available.
190    PreferredLeaderNotAvailable,
191    /// The consumer group has reached its max size.
192    GroupMaxSizeReached,
193    /// The broker rejected this static consumer since another consumer with the same group.instance.id has registered with a different member.id.
194    FencedInstanceId,
195    /// Eligible topic partition leaders are not available.
196    EligibleLeadersNotAvailable,
197    /// Leader election not needed for topic partition.
198    ElectionNotNeeded,
199    /// No partition reassignment is in progress.
200    NoReassignmentInProgress,
201    /// Deleting offsets of a topic is forbidden while the consumer group is actively subscribed to it.
202    GroupSubscribedToTopic,
203    /// This record has failed the validation on broker and hence will be rejected.
204    InvalidRecord,
205    /// There are unstable offsets that need to be cleared.
206    UnstableOffsetCommit,
207    /// The throttling quota has been exceeded.
208    ThrottlingQuotaExceeded,
209    /// There is a newer producer with the same transactionalId which fences the current one.
210    ProducerFenced,
211    /// A request illegally referred to a resource that does not exist.
212    ResourceNotFound,
213    /// A request illegally referred to the same resource twice.
214    DuplicateResource,
215    /// Requested credential would not meet criteria for acceptability.
216    UnacceptableCredential,
217    /// Indicates that the either the sender or recipient of a voter-only request is not one of the expected voters
218    InconsistentVoterSet,
219    /// The given update version was invalid.
220    InvalidUpdateVersion,
221    /// Unable to update finalized features due to an unexpected server error.
222    FeatureUpdateFailed,
223    /// Request principal deserialization failed during forwarding. This indicates an internal error on the broker cluster security setup.
224    PrincipalDeserializationFailure,
225    /// Requested snapshot was not found
226    SnapshotNotFound,
227    /// Requested position is not greater than or equal to zero, and less than the size of the snapshot.
228    PositionOutOfRange,
229    /// This server does not host this topic ID.
230    UnknownTopicId,
231    /// This broker ID is already in use.
232    DuplicateBrokerRegistration,
233    /// The given broker ID was not registered.
234    BrokerIdNotRegistered,
235    /// The log's topic ID did not match the topic ID in the request
236    InconsistentTopicId,
237    /// The clusterId in the request does not match that found on the server
238    InconsistentClusterId,
239    /// The transactionalId could not be found
240    TransactionalIdNotFound,
241    /// The fetch session encountered inconsistent topic ID usage
242    FetchSessionTopicIdError,
243    /// The new ISR contains at least one ineligible replica.
244    IneligibleReplica,
245    /// The AlterPartition request successfully updated the partition state but the leader has changed.
246    NewLeaderElected,
247    /// The requested offset is moved to tiered storage.
248    OffsetMovedToTieredStorage,
249    /// The member epoch is fenced by the group coordinator. The member must abandon all its partitions and rejoin.
250    FencedMemberEpoch,
251    /// The instance ID is still used by another member in the consumer group. That member must leave first.
252    UnreleasedInstanceId,
253    /// The assignor or its version range is not supported by the consumer group.
254    UnsupportedAssignor,
255    /// The member epoch is stale. The member must retry after receiving its updated member epoch via the ConsumerGroupHeartbeat API.
256    StaleMemberEpoch,
257    /// The request was sent to an endpoint of the wrong type.
258    MismatchedEndpointType,
259    /// This endpoint type is not supported yet.
260    UnsupportedEndpointType,
261    /// This controller ID is not known.
262    UnknownControllerId,
263    /// Client sent a push telemetry request with an invalid or outdated subscription ID.
264    UnknownSubscriptionId,
265    /// Client sent a push telemetry request larger than the maximum size the broker will accept.
266    TelemetryTooLarge,
267    /// The controller has considered the broker registration to be invalid.
268    InvalidRegistration,
269    /// The server encountered an error with the transaction. The client can abort the transaction to continue using this transactional ID.
270    TransactionAbortable,
271    /// The record state is invalid. The acknowledgement of delivery could not be completed.
272    InvalidRecordState,
273    /// The share session was not found.
274    ShareSessionNotFound,
275    /// The share session epoch is invalid.
276    InvalidShareSessionEpoch,
277    /// The share coordinator rejected the request because the share-group state epoch did not match.
278    FencedStateEpoch,
279    /// The voter key doesn't match the receiving replica's key.
280    InvalidVoterKey,
281    /// The voter is already part of the set of voters.
282    DuplicateVoter,
283    /// The voter is not part of the set of voters.
284    VoterNotFound,
285    /// The regular expression is not valid.
286    InvalidRegularExpression,
287    /// Client metadata is stale, client should rebootstrap to obtain new metadata.
288    RebootstrapRequired,
289    /// The supplied topology is invalid.
290    StreamsInvalidTopology,
291    /// The supplied topology epoch is invalid.
292    StreamsInvalidTopologyEpoch,
293    /// The supplied topology epoch is outdated.
294    StreamsTopologyFenced,
295    /// The limit of share sessions has been reached.
296    ShareSessionLimitReached,
297    /// A code this build has no name for.
298    ///
299    /// Carries the wire value so a UI can still show it and a bug report can
300    /// still identify it.
301    Unknown(i16),
302}
303
304impl ErrorCode {
305    /// The wire code.
306    pub const fn code(self) -> i16 {
307        match self {
308            ErrorCode::UnknownServerError => -1,
309            ErrorCode::OffsetOutOfRange => 1,
310            ErrorCode::CorruptMessage => 2,
311            ErrorCode::UnknownTopicOrPartition => 3,
312            ErrorCode::InvalidFetchSize => 4,
313            ErrorCode::LeaderNotAvailable => 5,
314            ErrorCode::NotLeaderOrFollower => 6,
315            ErrorCode::RequestTimedOut => 7,
316            ErrorCode::BrokerNotAvailable => 8,
317            ErrorCode::ReplicaNotAvailable => 9,
318            ErrorCode::MessageTooLarge => 10,
319            ErrorCode::StaleControllerEpoch => 11,
320            ErrorCode::OffsetMetadataTooLarge => 12,
321            ErrorCode::NetworkException => 13,
322            ErrorCode::CoordinatorLoadInProgress => 14,
323            ErrorCode::CoordinatorNotAvailable => 15,
324            ErrorCode::NotCoordinator => 16,
325            ErrorCode::InvalidTopicException => 17,
326            ErrorCode::RecordListTooLarge => 18,
327            ErrorCode::NotEnoughReplicas => 19,
328            ErrorCode::NotEnoughReplicasAfterAppend => 20,
329            ErrorCode::InvalidRequiredAcks => 21,
330            ErrorCode::IllegalGeneration => 22,
331            ErrorCode::InconsistentGroupProtocol => 23,
332            ErrorCode::InvalidGroupId => 24,
333            ErrorCode::UnknownMemberId => 25,
334            ErrorCode::InvalidSessionTimeout => 26,
335            ErrorCode::RebalanceInProgress => 27,
336            ErrorCode::InvalidCommitOffsetSize => 28,
337            ErrorCode::TopicAuthorizationFailed => 29,
338            ErrorCode::GroupAuthorizationFailed => 30,
339            ErrorCode::ClusterAuthorizationFailed => 31,
340            ErrorCode::InvalidTimestamp => 32,
341            ErrorCode::UnsupportedSaslMechanism => 33,
342            ErrorCode::IllegalSaslState => 34,
343            ErrorCode::UnsupportedVersion => 35,
344            ErrorCode::TopicAlreadyExists => 36,
345            ErrorCode::InvalidPartitions => 37,
346            ErrorCode::InvalidReplicationFactor => 38,
347            ErrorCode::InvalidReplicaAssignment => 39,
348            ErrorCode::InvalidConfig => 40,
349            ErrorCode::NotController => 41,
350            ErrorCode::InvalidRequest => 42,
351            ErrorCode::UnsupportedForMessageFormat => 43,
352            ErrorCode::PolicyViolation => 44,
353            ErrorCode::OutOfOrderSequenceNumber => 45,
354            ErrorCode::DuplicateSequenceNumber => 46,
355            ErrorCode::InvalidProducerEpoch => 47,
356            ErrorCode::InvalidTxnState => 48,
357            ErrorCode::InvalidProducerIdMapping => 49,
358            ErrorCode::InvalidTransactionTimeout => 50,
359            ErrorCode::ConcurrentTransactions => 51,
360            ErrorCode::TransactionCoordinatorFenced => 52,
361            ErrorCode::TransactionalIdAuthorizationFailed => 53,
362            ErrorCode::SecurityDisabled => 54,
363            ErrorCode::OperationNotAttempted => 55,
364            ErrorCode::KafkaStorageError => 56,
365            ErrorCode::LogDirNotFound => 57,
366            ErrorCode::SaslAuthenticationFailed => 58,
367            ErrorCode::UnknownProducerId => 59,
368            ErrorCode::ReassignmentInProgress => 60,
369            ErrorCode::DelegationTokenAuthDisabled => 61,
370            ErrorCode::DelegationTokenNotFound => 62,
371            ErrorCode::DelegationTokenOwnerMismatch => 63,
372            ErrorCode::DelegationTokenRequestNotAllowed => 64,
373            ErrorCode::DelegationTokenAuthorizationFailed => 65,
374            ErrorCode::DelegationTokenExpired => 66,
375            ErrorCode::InvalidPrincipalType => 67,
376            ErrorCode::NonEmptyGroup => 68,
377            ErrorCode::GroupIdNotFound => 69,
378            ErrorCode::FetchSessionIdNotFound => 70,
379            ErrorCode::InvalidFetchSessionEpoch => 71,
380            ErrorCode::ListenerNotFound => 72,
381            ErrorCode::TopicDeletionDisabled => 73,
382            ErrorCode::FencedLeaderEpoch => 74,
383            ErrorCode::UnknownLeaderEpoch => 75,
384            ErrorCode::UnsupportedCompressionType => 76,
385            ErrorCode::StaleBrokerEpoch => 77,
386            ErrorCode::OffsetNotAvailable => 78,
387            ErrorCode::MemberIdRequired => 79,
388            ErrorCode::PreferredLeaderNotAvailable => 80,
389            ErrorCode::GroupMaxSizeReached => 81,
390            ErrorCode::FencedInstanceId => 82,
391            ErrorCode::EligibleLeadersNotAvailable => 83,
392            ErrorCode::ElectionNotNeeded => 84,
393            ErrorCode::NoReassignmentInProgress => 85,
394            ErrorCode::GroupSubscribedToTopic => 86,
395            ErrorCode::InvalidRecord => 87,
396            ErrorCode::UnstableOffsetCommit => 88,
397            ErrorCode::ThrottlingQuotaExceeded => 89,
398            ErrorCode::ProducerFenced => 90,
399            ErrorCode::ResourceNotFound => 91,
400            ErrorCode::DuplicateResource => 92,
401            ErrorCode::UnacceptableCredential => 93,
402            ErrorCode::InconsistentVoterSet => 94,
403            ErrorCode::InvalidUpdateVersion => 95,
404            ErrorCode::FeatureUpdateFailed => 96,
405            ErrorCode::PrincipalDeserializationFailure => 97,
406            ErrorCode::SnapshotNotFound => 98,
407            ErrorCode::PositionOutOfRange => 99,
408            ErrorCode::UnknownTopicId => 100,
409            ErrorCode::DuplicateBrokerRegistration => 101,
410            ErrorCode::BrokerIdNotRegistered => 102,
411            ErrorCode::InconsistentTopicId => 103,
412            ErrorCode::InconsistentClusterId => 104,
413            ErrorCode::TransactionalIdNotFound => 105,
414            ErrorCode::FetchSessionTopicIdError => 106,
415            ErrorCode::IneligibleReplica => 107,
416            ErrorCode::NewLeaderElected => 108,
417            ErrorCode::OffsetMovedToTieredStorage => 109,
418            ErrorCode::FencedMemberEpoch => 110,
419            ErrorCode::UnreleasedInstanceId => 111,
420            ErrorCode::UnsupportedAssignor => 112,
421            ErrorCode::StaleMemberEpoch => 113,
422            ErrorCode::MismatchedEndpointType => 114,
423            ErrorCode::UnsupportedEndpointType => 115,
424            ErrorCode::UnknownControllerId => 116,
425            ErrorCode::UnknownSubscriptionId => 117,
426            ErrorCode::TelemetryTooLarge => 118,
427            ErrorCode::InvalidRegistration => 119,
428            ErrorCode::TransactionAbortable => 120,
429            ErrorCode::InvalidRecordState => 121,
430            ErrorCode::ShareSessionNotFound => 122,
431            ErrorCode::InvalidShareSessionEpoch => 123,
432            ErrorCode::FencedStateEpoch => 124,
433            ErrorCode::InvalidVoterKey => 125,
434            ErrorCode::DuplicateVoter => 126,
435            ErrorCode::VoterNotFound => 127,
436            ErrorCode::InvalidRegularExpression => 128,
437            ErrorCode::RebootstrapRequired => 129,
438            ErrorCode::StreamsInvalidTopology => 130,
439            ErrorCode::StreamsInvalidTopologyEpoch => 131,
440            ErrorCode::StreamsTopologyFenced => 132,
441            ErrorCode::ShareSessionLimitReached => 133,
442            ErrorCode::Unknown(code) => code,
443        }
444    }
445
446    /// The code's protocol name, or `None` for an unrecognised code.
447    pub const fn name(self) -> Option<&'static str> {
448        match self {
449            ErrorCode::UnknownServerError => Some("UNKNOWN_SERVER_ERROR"),
450            ErrorCode::OffsetOutOfRange => Some("OFFSET_OUT_OF_RANGE"),
451            ErrorCode::CorruptMessage => Some("CORRUPT_MESSAGE"),
452            ErrorCode::UnknownTopicOrPartition => Some("UNKNOWN_TOPIC_OR_PARTITION"),
453            ErrorCode::InvalidFetchSize => Some("INVALID_FETCH_SIZE"),
454            ErrorCode::LeaderNotAvailable => Some("LEADER_NOT_AVAILABLE"),
455            ErrorCode::NotLeaderOrFollower => Some("NOT_LEADER_OR_FOLLOWER"),
456            ErrorCode::RequestTimedOut => Some("REQUEST_TIMED_OUT"),
457            ErrorCode::BrokerNotAvailable => Some("BROKER_NOT_AVAILABLE"),
458            ErrorCode::ReplicaNotAvailable => Some("REPLICA_NOT_AVAILABLE"),
459            ErrorCode::MessageTooLarge => Some("MESSAGE_TOO_LARGE"),
460            ErrorCode::StaleControllerEpoch => Some("STALE_CONTROLLER_EPOCH"),
461            ErrorCode::OffsetMetadataTooLarge => Some("OFFSET_METADATA_TOO_LARGE"),
462            ErrorCode::NetworkException => Some("NETWORK_EXCEPTION"),
463            ErrorCode::CoordinatorLoadInProgress => Some("COORDINATOR_LOAD_IN_PROGRESS"),
464            ErrorCode::CoordinatorNotAvailable => Some("COORDINATOR_NOT_AVAILABLE"),
465            ErrorCode::NotCoordinator => Some("NOT_COORDINATOR"),
466            ErrorCode::InvalidTopicException => Some("INVALID_TOPIC_EXCEPTION"),
467            ErrorCode::RecordListTooLarge => Some("RECORD_LIST_TOO_LARGE"),
468            ErrorCode::NotEnoughReplicas => Some("NOT_ENOUGH_REPLICAS"),
469            ErrorCode::NotEnoughReplicasAfterAppend => Some("NOT_ENOUGH_REPLICAS_AFTER_APPEND"),
470            ErrorCode::InvalidRequiredAcks => Some("INVALID_REQUIRED_ACKS"),
471            ErrorCode::IllegalGeneration => Some("ILLEGAL_GENERATION"),
472            ErrorCode::InconsistentGroupProtocol => Some("INCONSISTENT_GROUP_PROTOCOL"),
473            ErrorCode::InvalidGroupId => Some("INVALID_GROUP_ID"),
474            ErrorCode::UnknownMemberId => Some("UNKNOWN_MEMBER_ID"),
475            ErrorCode::InvalidSessionTimeout => Some("INVALID_SESSION_TIMEOUT"),
476            ErrorCode::RebalanceInProgress => Some("REBALANCE_IN_PROGRESS"),
477            ErrorCode::InvalidCommitOffsetSize => Some("INVALID_COMMIT_OFFSET_SIZE"),
478            ErrorCode::TopicAuthorizationFailed => Some("TOPIC_AUTHORIZATION_FAILED"),
479            ErrorCode::GroupAuthorizationFailed => Some("GROUP_AUTHORIZATION_FAILED"),
480            ErrorCode::ClusterAuthorizationFailed => Some("CLUSTER_AUTHORIZATION_FAILED"),
481            ErrorCode::InvalidTimestamp => Some("INVALID_TIMESTAMP"),
482            ErrorCode::UnsupportedSaslMechanism => Some("UNSUPPORTED_SASL_MECHANISM"),
483            ErrorCode::IllegalSaslState => Some("ILLEGAL_SASL_STATE"),
484            ErrorCode::UnsupportedVersion => Some("UNSUPPORTED_VERSION"),
485            ErrorCode::TopicAlreadyExists => Some("TOPIC_ALREADY_EXISTS"),
486            ErrorCode::InvalidPartitions => Some("INVALID_PARTITIONS"),
487            ErrorCode::InvalidReplicationFactor => Some("INVALID_REPLICATION_FACTOR"),
488            ErrorCode::InvalidReplicaAssignment => Some("INVALID_REPLICA_ASSIGNMENT"),
489            ErrorCode::InvalidConfig => Some("INVALID_CONFIG"),
490            ErrorCode::NotController => Some("NOT_CONTROLLER"),
491            ErrorCode::InvalidRequest => Some("INVALID_REQUEST"),
492            ErrorCode::UnsupportedForMessageFormat => Some("UNSUPPORTED_FOR_MESSAGE_FORMAT"),
493            ErrorCode::PolicyViolation => Some("POLICY_VIOLATION"),
494            ErrorCode::OutOfOrderSequenceNumber => Some("OUT_OF_ORDER_SEQUENCE_NUMBER"),
495            ErrorCode::DuplicateSequenceNumber => Some("DUPLICATE_SEQUENCE_NUMBER"),
496            ErrorCode::InvalidProducerEpoch => Some("INVALID_PRODUCER_EPOCH"),
497            ErrorCode::InvalidTxnState => Some("INVALID_TXN_STATE"),
498            ErrorCode::InvalidProducerIdMapping => Some("INVALID_PRODUCER_ID_MAPPING"),
499            ErrorCode::InvalidTransactionTimeout => Some("INVALID_TRANSACTION_TIMEOUT"),
500            ErrorCode::ConcurrentTransactions => Some("CONCURRENT_TRANSACTIONS"),
501            ErrorCode::TransactionCoordinatorFenced => Some("TRANSACTION_COORDINATOR_FENCED"),
502            ErrorCode::TransactionalIdAuthorizationFailed => {
503                Some("TRANSACTIONAL_ID_AUTHORIZATION_FAILED")
504            }
505            ErrorCode::SecurityDisabled => Some("SECURITY_DISABLED"),
506            ErrorCode::OperationNotAttempted => Some("OPERATION_NOT_ATTEMPTED"),
507            ErrorCode::KafkaStorageError => Some("KAFKA_STORAGE_ERROR"),
508            ErrorCode::LogDirNotFound => Some("LOG_DIR_NOT_FOUND"),
509            ErrorCode::SaslAuthenticationFailed => Some("SASL_AUTHENTICATION_FAILED"),
510            ErrorCode::UnknownProducerId => Some("UNKNOWN_PRODUCER_ID"),
511            ErrorCode::ReassignmentInProgress => Some("REASSIGNMENT_IN_PROGRESS"),
512            ErrorCode::DelegationTokenAuthDisabled => Some("DELEGATION_TOKEN_AUTH_DISABLED"),
513            ErrorCode::DelegationTokenNotFound => Some("DELEGATION_TOKEN_NOT_FOUND"),
514            ErrorCode::DelegationTokenOwnerMismatch => Some("DELEGATION_TOKEN_OWNER_MISMATCH"),
515            ErrorCode::DelegationTokenRequestNotAllowed => {
516                Some("DELEGATION_TOKEN_REQUEST_NOT_ALLOWED")
517            }
518            ErrorCode::DelegationTokenAuthorizationFailed => {
519                Some("DELEGATION_TOKEN_AUTHORIZATION_FAILED")
520            }
521            ErrorCode::DelegationTokenExpired => Some("DELEGATION_TOKEN_EXPIRED"),
522            ErrorCode::InvalidPrincipalType => Some("INVALID_PRINCIPAL_TYPE"),
523            ErrorCode::NonEmptyGroup => Some("NON_EMPTY_GROUP"),
524            ErrorCode::GroupIdNotFound => Some("GROUP_ID_NOT_FOUND"),
525            ErrorCode::FetchSessionIdNotFound => Some("FETCH_SESSION_ID_NOT_FOUND"),
526            ErrorCode::InvalidFetchSessionEpoch => Some("INVALID_FETCH_SESSION_EPOCH"),
527            ErrorCode::ListenerNotFound => Some("LISTENER_NOT_FOUND"),
528            ErrorCode::TopicDeletionDisabled => Some("TOPIC_DELETION_DISABLED"),
529            ErrorCode::FencedLeaderEpoch => Some("FENCED_LEADER_EPOCH"),
530            ErrorCode::UnknownLeaderEpoch => Some("UNKNOWN_LEADER_EPOCH"),
531            ErrorCode::UnsupportedCompressionType => Some("UNSUPPORTED_COMPRESSION_TYPE"),
532            ErrorCode::StaleBrokerEpoch => Some("STALE_BROKER_EPOCH"),
533            ErrorCode::OffsetNotAvailable => Some("OFFSET_NOT_AVAILABLE"),
534            ErrorCode::MemberIdRequired => Some("MEMBER_ID_REQUIRED"),
535            ErrorCode::PreferredLeaderNotAvailable => Some("PREFERRED_LEADER_NOT_AVAILABLE"),
536            ErrorCode::GroupMaxSizeReached => Some("GROUP_MAX_SIZE_REACHED"),
537            ErrorCode::FencedInstanceId => Some("FENCED_INSTANCE_ID"),
538            ErrorCode::EligibleLeadersNotAvailable => Some("ELIGIBLE_LEADERS_NOT_AVAILABLE"),
539            ErrorCode::ElectionNotNeeded => Some("ELECTION_NOT_NEEDED"),
540            ErrorCode::NoReassignmentInProgress => Some("NO_REASSIGNMENT_IN_PROGRESS"),
541            ErrorCode::GroupSubscribedToTopic => Some("GROUP_SUBSCRIBED_TO_TOPIC"),
542            ErrorCode::InvalidRecord => Some("INVALID_RECORD"),
543            ErrorCode::UnstableOffsetCommit => Some("UNSTABLE_OFFSET_COMMIT"),
544            ErrorCode::ThrottlingQuotaExceeded => Some("THROTTLING_QUOTA_EXCEEDED"),
545            ErrorCode::ProducerFenced => Some("PRODUCER_FENCED"),
546            ErrorCode::ResourceNotFound => Some("RESOURCE_NOT_FOUND"),
547            ErrorCode::DuplicateResource => Some("DUPLICATE_RESOURCE"),
548            ErrorCode::UnacceptableCredential => Some("UNACCEPTABLE_CREDENTIAL"),
549            ErrorCode::InconsistentVoterSet => Some("INCONSISTENT_VOTER_SET"),
550            ErrorCode::InvalidUpdateVersion => Some("INVALID_UPDATE_VERSION"),
551            ErrorCode::FeatureUpdateFailed => Some("FEATURE_UPDATE_FAILED"),
552            ErrorCode::PrincipalDeserializationFailure => Some("PRINCIPAL_DESERIALIZATION_FAILURE"),
553            ErrorCode::SnapshotNotFound => Some("SNAPSHOT_NOT_FOUND"),
554            ErrorCode::PositionOutOfRange => Some("POSITION_OUT_OF_RANGE"),
555            ErrorCode::UnknownTopicId => Some("UNKNOWN_TOPIC_ID"),
556            ErrorCode::DuplicateBrokerRegistration => Some("DUPLICATE_BROKER_REGISTRATION"),
557            ErrorCode::BrokerIdNotRegistered => Some("BROKER_ID_NOT_REGISTERED"),
558            ErrorCode::InconsistentTopicId => Some("INCONSISTENT_TOPIC_ID"),
559            ErrorCode::InconsistentClusterId => Some("INCONSISTENT_CLUSTER_ID"),
560            ErrorCode::TransactionalIdNotFound => Some("TRANSACTIONAL_ID_NOT_FOUND"),
561            ErrorCode::FetchSessionTopicIdError => Some("FETCH_SESSION_TOPIC_ID_ERROR"),
562            ErrorCode::IneligibleReplica => Some("INELIGIBLE_REPLICA"),
563            ErrorCode::NewLeaderElected => Some("NEW_LEADER_ELECTED"),
564            ErrorCode::OffsetMovedToTieredStorage => Some("OFFSET_MOVED_TO_TIERED_STORAGE"),
565            ErrorCode::FencedMemberEpoch => Some("FENCED_MEMBER_EPOCH"),
566            ErrorCode::UnreleasedInstanceId => Some("UNRELEASED_INSTANCE_ID"),
567            ErrorCode::UnsupportedAssignor => Some("UNSUPPORTED_ASSIGNOR"),
568            ErrorCode::StaleMemberEpoch => Some("STALE_MEMBER_EPOCH"),
569            ErrorCode::MismatchedEndpointType => Some("MISMATCHED_ENDPOINT_TYPE"),
570            ErrorCode::UnsupportedEndpointType => Some("UNSUPPORTED_ENDPOINT_TYPE"),
571            ErrorCode::UnknownControllerId => Some("UNKNOWN_CONTROLLER_ID"),
572            ErrorCode::UnknownSubscriptionId => Some("UNKNOWN_SUBSCRIPTION_ID"),
573            ErrorCode::TelemetryTooLarge => Some("TELEMETRY_TOO_LARGE"),
574            ErrorCode::InvalidRegistration => Some("INVALID_REGISTRATION"),
575            ErrorCode::TransactionAbortable => Some("TRANSACTION_ABORTABLE"),
576            ErrorCode::InvalidRecordState => Some("INVALID_RECORD_STATE"),
577            ErrorCode::ShareSessionNotFound => Some("SHARE_SESSION_NOT_FOUND"),
578            ErrorCode::InvalidShareSessionEpoch => Some("INVALID_SHARE_SESSION_EPOCH"),
579            ErrorCode::FencedStateEpoch => Some("FENCED_STATE_EPOCH"),
580            ErrorCode::InvalidVoterKey => Some("INVALID_VOTER_KEY"),
581            ErrorCode::DuplicateVoter => Some("DUPLICATE_VOTER"),
582            ErrorCode::VoterNotFound => Some("VOTER_NOT_FOUND"),
583            ErrorCode::InvalidRegularExpression => Some("INVALID_REGULAR_EXPRESSION"),
584            ErrorCode::RebootstrapRequired => Some("REBOOTSTRAP_REQUIRED"),
585            ErrorCode::StreamsInvalidTopology => Some("STREAMS_INVALID_TOPOLOGY"),
586            ErrorCode::StreamsInvalidTopologyEpoch => Some("STREAMS_INVALID_TOPOLOGY_EPOCH"),
587            ErrorCode::StreamsTopologyFenced => Some("STREAMS_TOPOLOGY_FENCED"),
588            ErrorCode::ShareSessionLimitReached => Some("SHARE_SESSION_LIMIT_REACHED"),
589            ErrorCode::Unknown(_) => None,
590        }
591    }
592
593    /// The protocol's own description of the code.
594    pub const fn description(self) -> Option<&'static str> {
595        match self {
596            ErrorCode::UnknownServerError => {
597                Some("The server experienced an unexpected error when processing the request.")
598            }
599            ErrorCode::OffsetOutOfRange => Some(
600                "The requested offset is not within the range of offsets maintained by the server.",
601            ),
602            ErrorCode::CorruptMessage => Some(
603                "This message has failed its CRC checksum, exceeds the valid size, has a null key for a compacted topic, or is otherwise corrupt.",
604            ),
605            ErrorCode::UnknownTopicOrPartition => {
606                Some("This server does not host this topic-partition.")
607            }
608            ErrorCode::InvalidFetchSize => Some("The requested fetch size is invalid."),
609            ErrorCode::LeaderNotAvailable => Some(
610                "There is no leader for this topic-partition as we are in the middle of a leadership election.",
611            ),
612            ErrorCode::NotLeaderOrFollower => Some(
613                "For requests intended only for the leader, this error indicates that the broker is not the current leader. For requests intended for any replica, this error indicates that the broker is not a replica of the topic partition.",
614            ),
615            ErrorCode::RequestTimedOut => Some("The request timed out."),
616            ErrorCode::BrokerNotAvailable => Some("The broker is not available."),
617            ErrorCode::ReplicaNotAvailable => Some(
618                "The replica is not available for the requested topic-partition. Produce/Fetch requests and other requests intended only for the leader or follower return NOT_LEADER_OR_FOLLOWER if the broker is not a replica of the topic-partition.",
619            ),
620            ErrorCode::MessageTooLarge => Some(
621                "The request included a message larger than the max message size the server will accept.",
622            ),
623            ErrorCode::StaleControllerEpoch => Some("The controller moved to another broker."),
624            ErrorCode::OffsetMetadataTooLarge => {
625                Some("The metadata field of the offset request was too large.")
626            }
627            ErrorCode::NetworkException => {
628                Some("The server disconnected before a response was received.")
629            }
630            ErrorCode::CoordinatorLoadInProgress => {
631                Some("The coordinator is loading and hence can't process requests.")
632            }
633            ErrorCode::CoordinatorNotAvailable => Some("The coordinator is not available."),
634            ErrorCode::NotCoordinator => Some("This is not the correct coordinator."),
635            ErrorCode::InvalidTopicException => {
636                Some("The request attempted to perform an operation on an invalid topic.")
637            }
638            ErrorCode::RecordListTooLarge => Some(
639                "The request included message batch larger than the configured segment size on the server.",
640            ),
641            ErrorCode::NotEnoughReplicas => {
642                Some("Messages are rejected since there are fewer in-sync replicas than required.")
643            }
644            ErrorCode::NotEnoughReplicasAfterAppend => Some(
645                "Messages are written to the log, but to fewer in-sync replicas than required.",
646            ),
647            ErrorCode::InvalidRequiredAcks => {
648                Some("Produce request specified an invalid value for required acks.")
649            }
650            ErrorCode::IllegalGeneration => Some("Specified group generation id is not valid."),
651            ErrorCode::InconsistentGroupProtocol => Some(
652                "The group member's supported protocols are incompatible with those of existing members or first group member tried to join with empty protocol type or empty protocol list.",
653            ),
654            ErrorCode::InvalidGroupId => Some("The configured groupId is invalid."),
655            ErrorCode::UnknownMemberId => Some("The coordinator is not aware of this member."),
656            ErrorCode::InvalidSessionTimeout => Some(
657                "The session timeout is not within the range allowed by the broker (as configured by group.min.session.timeout.ms and group.max.session.timeout.ms).",
658            ),
659            ErrorCode::RebalanceInProgress => {
660                Some("The group is rebalancing, so a rejoin is needed.")
661            }
662            ErrorCode::InvalidCommitOffsetSize => {
663                Some("The committing offset data size is not valid.")
664            }
665            ErrorCode::TopicAuthorizationFailed => Some("Topic authorization failed."),
666            ErrorCode::GroupAuthorizationFailed => Some("Group authorization failed."),
667            ErrorCode::ClusterAuthorizationFailed => Some("Cluster authorization failed."),
668            ErrorCode::InvalidTimestamp => {
669                Some("The timestamp of the message is out of acceptable range.")
670            }
671            ErrorCode::UnsupportedSaslMechanism => {
672                Some("The broker does not support the requested SASL mechanism.")
673            }
674            ErrorCode::IllegalSaslState => {
675                Some("Request is not valid given the current SASL state.")
676            }
677            ErrorCode::UnsupportedVersion => Some("The version of API is not supported."),
678            ErrorCode::TopicAlreadyExists => Some("Topic with this name already exists."),
679            ErrorCode::InvalidPartitions => Some("Number of partitions is below 1."),
680            ErrorCode::InvalidReplicationFactor => Some(
681                "Replication factor is below 1 or larger than the number of available brokers.",
682            ),
683            ErrorCode::InvalidReplicaAssignment => Some("Replica assignment is invalid."),
684            ErrorCode::InvalidConfig => Some("Configuration is invalid."),
685            ErrorCode::NotController => {
686                Some("This is not the correct controller for this cluster.")
687            }
688            ErrorCode::InvalidRequest => Some(
689                "This most likely occurs because of a request being malformed by the client library or the message was sent to an incompatible broker. See the broker logs for more details.",
690            ),
691            ErrorCode::UnsupportedForMessageFormat => {
692                Some("The message format version on the broker does not support the request.")
693            }
694            ErrorCode::PolicyViolation => {
695                Some("Request parameters do not satisfy the configured policy.")
696            }
697            ErrorCode::OutOfOrderSequenceNumber => {
698                Some("The broker received an out of order sequence number.")
699            }
700            ErrorCode::DuplicateSequenceNumber => {
701                Some("The broker received a duplicate sequence number.")
702            }
703            ErrorCode::InvalidProducerEpoch => {
704                Some("Producer attempted to produce with an old epoch.")
705            }
706            ErrorCode::InvalidTxnState => {
707                Some("The producer attempted a transactional operation in an invalid state.")
708            }
709            ErrorCode::InvalidProducerIdMapping => Some(
710                "The producer attempted to use a producer id which is not currently assigned to its transactional id.",
711            ),
712            ErrorCode::InvalidTransactionTimeout => Some(
713                "The transaction timeout is larger than the maximum value allowed by the broker (as configured by transaction.max.timeout.ms).",
714            ),
715            ErrorCode::ConcurrentTransactions => Some(
716                "The producer attempted to update a transaction while another concurrent operation on the same transaction was ongoing.",
717            ),
718            ErrorCode::TransactionCoordinatorFenced => Some(
719                "Indicates that the transaction coordinator sending a WriteTxnMarker is no longer the current coordinator for a given producer.",
720            ),
721            ErrorCode::TransactionalIdAuthorizationFailed => {
722                Some("Transactional Id authorization failed.")
723            }
724            ErrorCode::SecurityDisabled => Some("Security features are disabled."),
725            ErrorCode::OperationNotAttempted => Some(
726                "The broker did not attempt to execute this operation. This may happen for batched RPCs where some operations in the batch failed, causing the broker to respond without trying the rest.",
727            ),
728            ErrorCode::KafkaStorageError => {
729                Some("Disk error when trying to access log file on the disk.")
730            }
731            ErrorCode::LogDirNotFound => {
732                Some("The user-specified log directory is not found in the broker config.")
733            }
734            ErrorCode::SaslAuthenticationFailed => Some("SASL Authentication failed."),
735            ErrorCode::UnknownProducerId => Some(
736                "This exception is raised by the broker if it could not locate the producer metadata associated with the producerId in question. This could happen if, for instance, the producer's records were deleted because their retention time had elapsed. Once the last records of the producerId are removed, the producer's metadata is removed from the broker, and future appends by the producer will return this exception.",
737            ),
738            ErrorCode::ReassignmentInProgress => Some("A partition reassignment is in progress."),
739            ErrorCode::DelegationTokenAuthDisabled => {
740                Some("Delegation Token feature is not enabled.")
741            }
742            ErrorCode::DelegationTokenNotFound => Some("Delegation Token is not found on server."),
743            ErrorCode::DelegationTokenOwnerMismatch => {
744                Some("Specified Principal is not valid Owner/Renewer.")
745            }
746            ErrorCode::DelegationTokenRequestNotAllowed => Some(
747                "Delegation Token requests are not allowed on PLAINTEXT/1-way SSL channels and on delegation token authenticated channels.",
748            ),
749            ErrorCode::DelegationTokenAuthorizationFailed => {
750                Some("Delegation Token authorization failed.")
751            }
752            ErrorCode::DelegationTokenExpired => Some("Delegation Token is expired."),
753            ErrorCode::InvalidPrincipalType => Some("Supplied principalType is not supported."),
754            ErrorCode::NonEmptyGroup => Some("The group is not empty."),
755            ErrorCode::GroupIdNotFound => Some("The group id does not exist."),
756            ErrorCode::FetchSessionIdNotFound => Some("The fetch session ID was not found."),
757            ErrorCode::InvalidFetchSessionEpoch => Some("The fetch session epoch is invalid."),
758            ErrorCode::ListenerNotFound => Some(
759                "There is no listener on the leader broker that matches the listener on which metadata request was processed.",
760            ),
761            ErrorCode::TopicDeletionDisabled => Some("Topic deletion is disabled."),
762            ErrorCode::FencedLeaderEpoch => {
763                Some("The leader epoch in the request is older than the epoch on the broker.")
764            }
765            ErrorCode::UnknownLeaderEpoch => {
766                Some("The leader epoch in the request is newer than the epoch on the broker.")
767            }
768            ErrorCode::UnsupportedCompressionType => Some(
769                "The requesting client does not support the compression type of given partition.",
770            ),
771            ErrorCode::StaleBrokerEpoch => Some("Broker epoch has changed."),
772            ErrorCode::OffsetNotAvailable => Some(
773                "The leader high watermark has not caught up from a recent leader election so the offsets cannot be guaranteed to be monotonically increasing.",
774            ),
775            ErrorCode::MemberIdRequired => Some(
776                "The group member needs to have a valid member id before actually entering a consumer group.",
777            ),
778            ErrorCode::PreferredLeaderNotAvailable => {
779                Some("The preferred leader was not available.")
780            }
781            ErrorCode::GroupMaxSizeReached => Some("The consumer group has reached its max size."),
782            ErrorCode::FencedInstanceId => Some(
783                "The broker rejected this static consumer since another consumer with the same group.instance.id has registered with a different member.id.",
784            ),
785            ErrorCode::EligibleLeadersNotAvailable => {
786                Some("Eligible topic partition leaders are not available.")
787            }
788            ErrorCode::ElectionNotNeeded => Some("Leader election not needed for topic partition."),
789            ErrorCode::NoReassignmentInProgress => {
790                Some("No partition reassignment is in progress.")
791            }
792            ErrorCode::GroupSubscribedToTopic => Some(
793                "Deleting offsets of a topic is forbidden while the consumer group is actively subscribed to it.",
794            ),
795            ErrorCode::InvalidRecord => {
796                Some("This record has failed the validation on broker and hence will be rejected.")
797            }
798            ErrorCode::UnstableOffsetCommit => {
799                Some("There are unstable offsets that need to be cleared.")
800            }
801            ErrorCode::ThrottlingQuotaExceeded => Some("The throttling quota has been exceeded."),
802            ErrorCode::ProducerFenced => Some(
803                "There is a newer producer with the same transactionalId which fences the current one.",
804            ),
805            ErrorCode::ResourceNotFound => {
806                Some("A request illegally referred to a resource that does not exist.")
807            }
808            ErrorCode::DuplicateResource => {
809                Some("A request illegally referred to the same resource twice.")
810            }
811            ErrorCode::UnacceptableCredential => {
812                Some("Requested credential would not meet criteria for acceptability.")
813            }
814            ErrorCode::InconsistentVoterSet => Some(
815                "Indicates that the either the sender or recipient of a voter-only request is not one of the expected voters",
816            ),
817            ErrorCode::InvalidUpdateVersion => Some("The given update version was invalid."),
818            ErrorCode::FeatureUpdateFailed => {
819                Some("Unable to update finalized features due to an unexpected server error.")
820            }
821            ErrorCode::PrincipalDeserializationFailure => Some(
822                "Request principal deserialization failed during forwarding. This indicates an internal error on the broker cluster security setup.",
823            ),
824            ErrorCode::SnapshotNotFound => Some("Requested snapshot was not found"),
825            ErrorCode::PositionOutOfRange => Some(
826                "Requested position is not greater than or equal to zero, and less than the size of the snapshot.",
827            ),
828            ErrorCode::UnknownTopicId => Some("This server does not host this topic ID."),
829            ErrorCode::DuplicateBrokerRegistration => Some("This broker ID is already in use."),
830            ErrorCode::BrokerIdNotRegistered => Some("The given broker ID was not registered."),
831            ErrorCode::InconsistentTopicId => {
832                Some("The log's topic ID did not match the topic ID in the request")
833            }
834            ErrorCode::InconsistentClusterId => {
835                Some("The clusterId in the request does not match that found on the server")
836            }
837            ErrorCode::TransactionalIdNotFound => Some("The transactionalId could not be found"),
838            ErrorCode::FetchSessionTopicIdError => {
839                Some("The fetch session encountered inconsistent topic ID usage")
840            }
841            ErrorCode::IneligibleReplica => {
842                Some("The new ISR contains at least one ineligible replica.")
843            }
844            ErrorCode::NewLeaderElected => Some(
845                "The AlterPartition request successfully updated the partition state but the leader has changed.",
846            ),
847            ErrorCode::OffsetMovedToTieredStorage => {
848                Some("The requested offset is moved to tiered storage.")
849            }
850            ErrorCode::FencedMemberEpoch => Some(
851                "The member epoch is fenced by the group coordinator. The member must abandon all its partitions and rejoin.",
852            ),
853            ErrorCode::UnreleasedInstanceId => Some(
854                "The instance ID is still used by another member in the consumer group. That member must leave first.",
855            ),
856            ErrorCode::UnsupportedAssignor => {
857                Some("The assignor or its version range is not supported by the consumer group.")
858            }
859            ErrorCode::StaleMemberEpoch => Some(
860                "The member epoch is stale. The member must retry after receiving its updated member epoch via the ConsumerGroupHeartbeat API.",
861            ),
862            ErrorCode::MismatchedEndpointType => {
863                Some("The request was sent to an endpoint of the wrong type.")
864            }
865            ErrorCode::UnsupportedEndpointType => Some("This endpoint type is not supported yet."),
866            ErrorCode::UnknownControllerId => Some("This controller ID is not known."),
867            ErrorCode::UnknownSubscriptionId => Some(
868                "Client sent a push telemetry request with an invalid or outdated subscription ID.",
869            ),
870            ErrorCode::TelemetryTooLarge => Some(
871                "Client sent a push telemetry request larger than the maximum size the broker will accept.",
872            ),
873            ErrorCode::InvalidRegistration => {
874                Some("The controller has considered the broker registration to be invalid.")
875            }
876            ErrorCode::TransactionAbortable => Some(
877                "The server encountered an error with the transaction. The client can abort the transaction to continue using this transactional ID.",
878            ),
879            ErrorCode::InvalidRecordState => Some(
880                "The record state is invalid. The acknowledgement of delivery could not be completed.",
881            ),
882            ErrorCode::ShareSessionNotFound => Some("The share session was not found."),
883            ErrorCode::InvalidShareSessionEpoch => Some("The share session epoch is invalid."),
884            ErrorCode::FencedStateEpoch => Some(
885                "The share coordinator rejected the request because the share-group state epoch did not match.",
886            ),
887            ErrorCode::InvalidVoterKey => {
888                Some("The voter key doesn't match the receiving replica's key.")
889            }
890            ErrorCode::DuplicateVoter => Some("The voter is already part of the set of voters."),
891            ErrorCode::VoterNotFound => Some("The voter is not part of the set of voters."),
892            ErrorCode::InvalidRegularExpression => Some("The regular expression is not valid."),
893            ErrorCode::RebootstrapRequired => {
894                Some("Client metadata is stale, client should rebootstrap to obtain new metadata.")
895            }
896            ErrorCode::StreamsInvalidTopology => Some("The supplied topology is invalid."),
897            ErrorCode::StreamsInvalidTopologyEpoch => {
898                Some("The supplied topology epoch is invalid.")
899            }
900            ErrorCode::StreamsTopologyFenced => Some("The supplied topology epoch is outdated."),
901            ErrorCode::ShareSessionLimitReached => {
902                Some("The limit of share sessions has been reached.")
903            }
904            ErrorCode::Unknown(_) => None,
905        }
906    }
907
908    /// Classify a wire code.
909    ///
910    /// `0` means success and has no `ErrorCode`; callers get `None` and should
911    /// treat the response as good.
912    pub fn from_code(code: i16) -> Option<Self> {
913        ResponseError::try_from_code(code).map(Self::from_response_error)
914    }
915
916    /// Convert an upstream `ResponseError`.
917    ///
918    /// Exhaustive on purpose: see the module docs.
919    fn from_response_error(err: ResponseError) -> Self {
920        match err {
921            ResponseError::UnknownServerError => ErrorCode::UnknownServerError,
922            ResponseError::OffsetOutOfRange => ErrorCode::OffsetOutOfRange,
923            ResponseError::CorruptMessage => ErrorCode::CorruptMessage,
924            ResponseError::UnknownTopicOrPartition => ErrorCode::UnknownTopicOrPartition,
925            ResponseError::InvalidFetchSize => ErrorCode::InvalidFetchSize,
926            ResponseError::LeaderNotAvailable => ErrorCode::LeaderNotAvailable,
927            ResponseError::NotLeaderOrFollower => ErrorCode::NotLeaderOrFollower,
928            ResponseError::RequestTimedOut => ErrorCode::RequestTimedOut,
929            ResponseError::BrokerNotAvailable => ErrorCode::BrokerNotAvailable,
930            ResponseError::ReplicaNotAvailable => ErrorCode::ReplicaNotAvailable,
931            ResponseError::MessageTooLarge => ErrorCode::MessageTooLarge,
932            ResponseError::StaleControllerEpoch => ErrorCode::StaleControllerEpoch,
933            ResponseError::OffsetMetadataTooLarge => ErrorCode::OffsetMetadataTooLarge,
934            ResponseError::NetworkException => ErrorCode::NetworkException,
935            ResponseError::CoordinatorLoadInProgress => ErrorCode::CoordinatorLoadInProgress,
936            ResponseError::CoordinatorNotAvailable => ErrorCode::CoordinatorNotAvailable,
937            ResponseError::NotCoordinator => ErrorCode::NotCoordinator,
938            ResponseError::InvalidTopicException => ErrorCode::InvalidTopicException,
939            ResponseError::RecordListTooLarge => ErrorCode::RecordListTooLarge,
940            ResponseError::NotEnoughReplicas => ErrorCode::NotEnoughReplicas,
941            ResponseError::NotEnoughReplicasAfterAppend => ErrorCode::NotEnoughReplicasAfterAppend,
942            ResponseError::InvalidRequiredAcks => ErrorCode::InvalidRequiredAcks,
943            ResponseError::IllegalGeneration => ErrorCode::IllegalGeneration,
944            ResponseError::InconsistentGroupProtocol => ErrorCode::InconsistentGroupProtocol,
945            ResponseError::InvalidGroupId => ErrorCode::InvalidGroupId,
946            ResponseError::UnknownMemberId => ErrorCode::UnknownMemberId,
947            ResponseError::InvalidSessionTimeout => ErrorCode::InvalidSessionTimeout,
948            ResponseError::RebalanceInProgress => ErrorCode::RebalanceInProgress,
949            ResponseError::InvalidCommitOffsetSize => ErrorCode::InvalidCommitOffsetSize,
950            ResponseError::TopicAuthorizationFailed => ErrorCode::TopicAuthorizationFailed,
951            ResponseError::GroupAuthorizationFailed => ErrorCode::GroupAuthorizationFailed,
952            ResponseError::ClusterAuthorizationFailed => ErrorCode::ClusterAuthorizationFailed,
953            ResponseError::InvalidTimestamp => ErrorCode::InvalidTimestamp,
954            ResponseError::UnsupportedSaslMechanism => ErrorCode::UnsupportedSaslMechanism,
955            ResponseError::IllegalSaslState => ErrorCode::IllegalSaslState,
956            ResponseError::UnsupportedVersion => ErrorCode::UnsupportedVersion,
957            ResponseError::TopicAlreadyExists => ErrorCode::TopicAlreadyExists,
958            ResponseError::InvalidPartitions => ErrorCode::InvalidPartitions,
959            ResponseError::InvalidReplicationFactor => ErrorCode::InvalidReplicationFactor,
960            ResponseError::InvalidReplicaAssignment => ErrorCode::InvalidReplicaAssignment,
961            ResponseError::InvalidConfig => ErrorCode::InvalidConfig,
962            ResponseError::NotController => ErrorCode::NotController,
963            ResponseError::InvalidRequest => ErrorCode::InvalidRequest,
964            ResponseError::UnsupportedForMessageFormat => ErrorCode::UnsupportedForMessageFormat,
965            ResponseError::PolicyViolation => ErrorCode::PolicyViolation,
966            ResponseError::OutOfOrderSequenceNumber => ErrorCode::OutOfOrderSequenceNumber,
967            ResponseError::DuplicateSequenceNumber => ErrorCode::DuplicateSequenceNumber,
968            ResponseError::InvalidProducerEpoch => ErrorCode::InvalidProducerEpoch,
969            ResponseError::InvalidTxnState => ErrorCode::InvalidTxnState,
970            ResponseError::InvalidProducerIdMapping => ErrorCode::InvalidProducerIdMapping,
971            ResponseError::InvalidTransactionTimeout => ErrorCode::InvalidTransactionTimeout,
972            ResponseError::ConcurrentTransactions => ErrorCode::ConcurrentTransactions,
973            ResponseError::TransactionCoordinatorFenced => ErrorCode::TransactionCoordinatorFenced,
974            ResponseError::TransactionalIdAuthorizationFailed => {
975                ErrorCode::TransactionalIdAuthorizationFailed
976            }
977            ResponseError::SecurityDisabled => ErrorCode::SecurityDisabled,
978            ResponseError::OperationNotAttempted => ErrorCode::OperationNotAttempted,
979            ResponseError::KafkaStorageError => ErrorCode::KafkaStorageError,
980            ResponseError::LogDirNotFound => ErrorCode::LogDirNotFound,
981            ResponseError::SaslAuthenticationFailed => ErrorCode::SaslAuthenticationFailed,
982            ResponseError::UnknownProducerId => ErrorCode::UnknownProducerId,
983            ResponseError::ReassignmentInProgress => ErrorCode::ReassignmentInProgress,
984            ResponseError::DelegationTokenAuthDisabled => ErrorCode::DelegationTokenAuthDisabled,
985            ResponseError::DelegationTokenNotFound => ErrorCode::DelegationTokenNotFound,
986            ResponseError::DelegationTokenOwnerMismatch => ErrorCode::DelegationTokenOwnerMismatch,
987            ResponseError::DelegationTokenRequestNotAllowed => {
988                ErrorCode::DelegationTokenRequestNotAllowed
989            }
990            ResponseError::DelegationTokenAuthorizationFailed => {
991                ErrorCode::DelegationTokenAuthorizationFailed
992            }
993            ResponseError::DelegationTokenExpired => ErrorCode::DelegationTokenExpired,
994            ResponseError::InvalidPrincipalType => ErrorCode::InvalidPrincipalType,
995            ResponseError::NonEmptyGroup => ErrorCode::NonEmptyGroup,
996            ResponseError::GroupIdNotFound => ErrorCode::GroupIdNotFound,
997            ResponseError::FetchSessionIdNotFound => ErrorCode::FetchSessionIdNotFound,
998            ResponseError::InvalidFetchSessionEpoch => ErrorCode::InvalidFetchSessionEpoch,
999            ResponseError::ListenerNotFound => ErrorCode::ListenerNotFound,
1000            ResponseError::TopicDeletionDisabled => ErrorCode::TopicDeletionDisabled,
1001            ResponseError::FencedLeaderEpoch => ErrorCode::FencedLeaderEpoch,
1002            ResponseError::UnknownLeaderEpoch => ErrorCode::UnknownLeaderEpoch,
1003            ResponseError::UnsupportedCompressionType => ErrorCode::UnsupportedCompressionType,
1004            ResponseError::StaleBrokerEpoch => ErrorCode::StaleBrokerEpoch,
1005            ResponseError::OffsetNotAvailable => ErrorCode::OffsetNotAvailable,
1006            ResponseError::MemberIdRequired => ErrorCode::MemberIdRequired,
1007            ResponseError::PreferredLeaderNotAvailable => ErrorCode::PreferredLeaderNotAvailable,
1008            ResponseError::GroupMaxSizeReached => ErrorCode::GroupMaxSizeReached,
1009            ResponseError::FencedInstanceId => ErrorCode::FencedInstanceId,
1010            ResponseError::EligibleLeadersNotAvailable => ErrorCode::EligibleLeadersNotAvailable,
1011            ResponseError::ElectionNotNeeded => ErrorCode::ElectionNotNeeded,
1012            ResponseError::NoReassignmentInProgress => ErrorCode::NoReassignmentInProgress,
1013            ResponseError::GroupSubscribedToTopic => ErrorCode::GroupSubscribedToTopic,
1014            ResponseError::InvalidRecord => ErrorCode::InvalidRecord,
1015            ResponseError::UnstableOffsetCommit => ErrorCode::UnstableOffsetCommit,
1016            ResponseError::ThrottlingQuotaExceeded => ErrorCode::ThrottlingQuotaExceeded,
1017            ResponseError::ProducerFenced => ErrorCode::ProducerFenced,
1018            ResponseError::ResourceNotFound => ErrorCode::ResourceNotFound,
1019            ResponseError::DuplicateResource => ErrorCode::DuplicateResource,
1020            ResponseError::UnacceptableCredential => ErrorCode::UnacceptableCredential,
1021            ResponseError::InconsistentVoterSet => ErrorCode::InconsistentVoterSet,
1022            ResponseError::InvalidUpdateVersion => ErrorCode::InvalidUpdateVersion,
1023            ResponseError::FeatureUpdateFailed => ErrorCode::FeatureUpdateFailed,
1024            ResponseError::PrincipalDeserializationFailure => {
1025                ErrorCode::PrincipalDeserializationFailure
1026            }
1027            ResponseError::SnapshotNotFound => ErrorCode::SnapshotNotFound,
1028            ResponseError::PositionOutOfRange => ErrorCode::PositionOutOfRange,
1029            ResponseError::UnknownTopicId => ErrorCode::UnknownTopicId,
1030            ResponseError::DuplicateBrokerRegistration => ErrorCode::DuplicateBrokerRegistration,
1031            ResponseError::BrokerIdNotRegistered => ErrorCode::BrokerIdNotRegistered,
1032            ResponseError::InconsistentTopicId => ErrorCode::InconsistentTopicId,
1033            ResponseError::InconsistentClusterId => ErrorCode::InconsistentClusterId,
1034            ResponseError::TransactionalIdNotFound => ErrorCode::TransactionalIdNotFound,
1035            ResponseError::FetchSessionTopicIdError => ErrorCode::FetchSessionTopicIdError,
1036            ResponseError::IneligibleReplica => ErrorCode::IneligibleReplica,
1037            ResponseError::NewLeaderElected => ErrorCode::NewLeaderElected,
1038            ResponseError::OffsetMovedToTieredStorage => ErrorCode::OffsetMovedToTieredStorage,
1039            ResponseError::FencedMemberEpoch => ErrorCode::FencedMemberEpoch,
1040            ResponseError::UnreleasedInstanceId => ErrorCode::UnreleasedInstanceId,
1041            ResponseError::UnsupportedAssignor => ErrorCode::UnsupportedAssignor,
1042            ResponseError::StaleMemberEpoch => ErrorCode::StaleMemberEpoch,
1043            ResponseError::MismatchedEndpointType => ErrorCode::MismatchedEndpointType,
1044            ResponseError::UnsupportedEndpointType => ErrorCode::UnsupportedEndpointType,
1045            ResponseError::UnknownControllerId => ErrorCode::UnknownControllerId,
1046            ResponseError::UnknownSubscriptionId => ErrorCode::UnknownSubscriptionId,
1047            ResponseError::TelemetryTooLarge => ErrorCode::TelemetryTooLarge,
1048            ResponseError::InvalidRegistration => ErrorCode::InvalidRegistration,
1049            ResponseError::TransactionAbortable => ErrorCode::TransactionAbortable,
1050            ResponseError::InvalidRecordState => ErrorCode::InvalidRecordState,
1051            ResponseError::ShareSessionNotFound => ErrorCode::ShareSessionNotFound,
1052            ResponseError::InvalidShareSessionEpoch => ErrorCode::InvalidShareSessionEpoch,
1053            ResponseError::FencedStateEpoch => ErrorCode::FencedStateEpoch,
1054            ResponseError::InvalidVoterKey => ErrorCode::InvalidVoterKey,
1055            ResponseError::DuplicateVoter => ErrorCode::DuplicateVoter,
1056            ResponseError::VoterNotFound => ErrorCode::VoterNotFound,
1057            ResponseError::InvalidRegularExpression => ErrorCode::InvalidRegularExpression,
1058            ResponseError::RebootstrapRequired => ErrorCode::RebootstrapRequired,
1059            ResponseError::StreamsInvalidTopology => ErrorCode::StreamsInvalidTopology,
1060            ResponseError::StreamsInvalidTopologyEpoch => ErrorCode::StreamsInvalidTopologyEpoch,
1061            ResponseError::StreamsTopologyFenced => ErrorCode::StreamsTopologyFenced,
1062            ResponseError::ShareSessionLimitReached => ErrorCode::ShareSessionLimitReached,
1063            ResponseError::Unknown(code) => ErrorCode::Unknown(code),
1064        }
1065    }
1066
1067    /// Whether the protocol considers this code worth retrying.
1068    ///
1069    /// Delegated to the crate rather than re-stated here. `Unknown` is not
1070    /// retriable, matching what every other Kafka client does with a code it
1071    /// cannot interpret.
1072    pub fn retriable(self) -> bool {
1073        match self {
1074            ErrorCode::Unknown(_) => false,
1075            named => ResponseError::try_from_code(named.code())
1076                .map(|e| e.is_retriable())
1077                .unwrap_or(false),
1078        }
1079    }
1080
1081    /// Whether retrying is worthwhile when the request named a specific
1082    /// resource that the broker says does not exist.
1083    ///
1084    /// This exists because PLAN.md's M5 acceptance and the protocol disagree,
1085    /// and both are right about different things. Kafka calls
1086    /// `UNKNOWN_TOPIC_OR_PARTITION` *retriable*, and for a topic that is
1087    /// mid-creation or mid-propagation it genuinely is. For a describe of a
1088    /// topic a user typed into a search box it is not: the answer will be the
1089    /// same five times over, and retrying turns a typo into a spinner.
1090    ///
1091    /// So it is a separate axis rather than a correction to [`Self::retriable`].
1092    /// The protocol's answer stays the protocol's answer — derived, not
1093    /// overridden — and callers that named a resource ask this one instead.
1094    pub fn retriable_for_named_resource(self) -> bool {
1095        !matches!(
1096            self,
1097            ErrorCode::UnknownTopicOrPartition
1098                | ErrorCode::UnknownTopicId
1099                | ErrorCode::GroupIdNotFound
1100                | ErrorCode::TransactionalIdNotFound
1101                | ErrorCode::UnknownMemberId
1102                | ErrorCode::ResourceNotFound
1103                | ErrorCode::LogDirNotFound
1104        ) && self.retriable()
1105    }
1106
1107    /// Whether seeing this code should invalidate the metadata snapshot.
1108    ///
1109    /// Retrying a `NOT_LEADER_OR_FOLLOWER` against the same stale leader is an
1110    /// infinite loop that presents as a flaky cluster, so this axis exists
1111    /// separately from `retriable`.
1112    pub const fn needs_metadata_refresh(self) -> bool {
1113        matches!(
1114            self,
1115            ErrorCode::UnknownTopicOrPartition
1116                | ErrorCode::LeaderNotAvailable
1117                | ErrorCode::NotLeaderOrFollower
1118                | ErrorCode::BrokerNotAvailable
1119                | ErrorCode::ReplicaNotAvailable
1120                | ErrorCode::NetworkException
1121                | ErrorCode::NotController
1122                | ErrorCode::KafkaStorageError
1123                | ErrorCode::ListenerNotFound
1124                | ErrorCode::FencedLeaderEpoch
1125                | ErrorCode::UnknownLeaderEpoch
1126                | ErrorCode::OffsetNotAvailable
1127                | ErrorCode::PreferredLeaderNotAvailable
1128                | ErrorCode::UnknownTopicId
1129                | ErrorCode::InconsistentTopicId
1130                | ErrorCode::FetchSessionTopicIdError
1131                | ErrorCode::NewLeaderElected
1132                | ErrorCode::RebootstrapRequired
1133        )
1134    }
1135
1136    /// Whether seeing this code should invalidate a cached coordinator.
1137    ///
1138    /// Independent of the metadata axis: a group coordinator moving says
1139    /// nothing about partition leadership, and refreshing the wrong cache
1140    /// leaves the retry pointed at the same wrong broker.
1141    pub const fn needs_coordinator_refresh(self) -> bool {
1142        matches!(
1143            self,
1144            ErrorCode::CoordinatorLoadInProgress
1145                | ErrorCode::CoordinatorNotAvailable
1146                | ErrorCode::NotCoordinator
1147        )
1148    }
1149
1150    /// Whether this code means the credentials were rejected.
1151    pub const fn is_authentication(self) -> bool {
1152        matches!(
1153            self,
1154            ErrorCode::UnsupportedSaslMechanism
1155                | ErrorCode::IllegalSaslState
1156                | ErrorCode::SaslAuthenticationFailed
1157        )
1158    }
1159
1160    /// Whether this code means the principal lacked permission.
1161    pub const fn is_authorization(self) -> bool {
1162        matches!(
1163            self,
1164            ErrorCode::TopicAuthorizationFailed
1165                | ErrorCode::GroupAuthorizationFailed
1166                | ErrorCode::ClusterAuthorizationFailed
1167                | ErrorCode::TransactionalIdAuthorizationFailed
1168                | ErrorCode::DelegationTokenAuthorizationFailed
1169        )
1170    }
1171}
1172
1173impl std::fmt::Display for ErrorCode {
1174    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1175        match self.name() {
1176            Some(name) => write!(f, "{name}({})", self.code()),
1177            None => write!(f, "UNKNOWN({})", self.code()),
1178        }
1179    }
1180}
1181
1182/// Every code this build names, for table-driven tests and UI legends.
1183pub const KNOWN_ERROR_CODES: [ErrorCode; 134] = [
1184    ErrorCode::UnknownServerError,
1185    ErrorCode::OffsetOutOfRange,
1186    ErrorCode::CorruptMessage,
1187    ErrorCode::UnknownTopicOrPartition,
1188    ErrorCode::InvalidFetchSize,
1189    ErrorCode::LeaderNotAvailable,
1190    ErrorCode::NotLeaderOrFollower,
1191    ErrorCode::RequestTimedOut,
1192    ErrorCode::BrokerNotAvailable,
1193    ErrorCode::ReplicaNotAvailable,
1194    ErrorCode::MessageTooLarge,
1195    ErrorCode::StaleControllerEpoch,
1196    ErrorCode::OffsetMetadataTooLarge,
1197    ErrorCode::NetworkException,
1198    ErrorCode::CoordinatorLoadInProgress,
1199    ErrorCode::CoordinatorNotAvailable,
1200    ErrorCode::NotCoordinator,
1201    ErrorCode::InvalidTopicException,
1202    ErrorCode::RecordListTooLarge,
1203    ErrorCode::NotEnoughReplicas,
1204    ErrorCode::NotEnoughReplicasAfterAppend,
1205    ErrorCode::InvalidRequiredAcks,
1206    ErrorCode::IllegalGeneration,
1207    ErrorCode::InconsistentGroupProtocol,
1208    ErrorCode::InvalidGroupId,
1209    ErrorCode::UnknownMemberId,
1210    ErrorCode::InvalidSessionTimeout,
1211    ErrorCode::RebalanceInProgress,
1212    ErrorCode::InvalidCommitOffsetSize,
1213    ErrorCode::TopicAuthorizationFailed,
1214    ErrorCode::GroupAuthorizationFailed,
1215    ErrorCode::ClusterAuthorizationFailed,
1216    ErrorCode::InvalidTimestamp,
1217    ErrorCode::UnsupportedSaslMechanism,
1218    ErrorCode::IllegalSaslState,
1219    ErrorCode::UnsupportedVersion,
1220    ErrorCode::TopicAlreadyExists,
1221    ErrorCode::InvalidPartitions,
1222    ErrorCode::InvalidReplicationFactor,
1223    ErrorCode::InvalidReplicaAssignment,
1224    ErrorCode::InvalidConfig,
1225    ErrorCode::NotController,
1226    ErrorCode::InvalidRequest,
1227    ErrorCode::UnsupportedForMessageFormat,
1228    ErrorCode::PolicyViolation,
1229    ErrorCode::OutOfOrderSequenceNumber,
1230    ErrorCode::DuplicateSequenceNumber,
1231    ErrorCode::InvalidProducerEpoch,
1232    ErrorCode::InvalidTxnState,
1233    ErrorCode::InvalidProducerIdMapping,
1234    ErrorCode::InvalidTransactionTimeout,
1235    ErrorCode::ConcurrentTransactions,
1236    ErrorCode::TransactionCoordinatorFenced,
1237    ErrorCode::TransactionalIdAuthorizationFailed,
1238    ErrorCode::SecurityDisabled,
1239    ErrorCode::OperationNotAttempted,
1240    ErrorCode::KafkaStorageError,
1241    ErrorCode::LogDirNotFound,
1242    ErrorCode::SaslAuthenticationFailed,
1243    ErrorCode::UnknownProducerId,
1244    ErrorCode::ReassignmentInProgress,
1245    ErrorCode::DelegationTokenAuthDisabled,
1246    ErrorCode::DelegationTokenNotFound,
1247    ErrorCode::DelegationTokenOwnerMismatch,
1248    ErrorCode::DelegationTokenRequestNotAllowed,
1249    ErrorCode::DelegationTokenAuthorizationFailed,
1250    ErrorCode::DelegationTokenExpired,
1251    ErrorCode::InvalidPrincipalType,
1252    ErrorCode::NonEmptyGroup,
1253    ErrorCode::GroupIdNotFound,
1254    ErrorCode::FetchSessionIdNotFound,
1255    ErrorCode::InvalidFetchSessionEpoch,
1256    ErrorCode::ListenerNotFound,
1257    ErrorCode::TopicDeletionDisabled,
1258    ErrorCode::FencedLeaderEpoch,
1259    ErrorCode::UnknownLeaderEpoch,
1260    ErrorCode::UnsupportedCompressionType,
1261    ErrorCode::StaleBrokerEpoch,
1262    ErrorCode::OffsetNotAvailable,
1263    ErrorCode::MemberIdRequired,
1264    ErrorCode::PreferredLeaderNotAvailable,
1265    ErrorCode::GroupMaxSizeReached,
1266    ErrorCode::FencedInstanceId,
1267    ErrorCode::EligibleLeadersNotAvailable,
1268    ErrorCode::ElectionNotNeeded,
1269    ErrorCode::NoReassignmentInProgress,
1270    ErrorCode::GroupSubscribedToTopic,
1271    ErrorCode::InvalidRecord,
1272    ErrorCode::UnstableOffsetCommit,
1273    ErrorCode::ThrottlingQuotaExceeded,
1274    ErrorCode::ProducerFenced,
1275    ErrorCode::ResourceNotFound,
1276    ErrorCode::DuplicateResource,
1277    ErrorCode::UnacceptableCredential,
1278    ErrorCode::InconsistentVoterSet,
1279    ErrorCode::InvalidUpdateVersion,
1280    ErrorCode::FeatureUpdateFailed,
1281    ErrorCode::PrincipalDeserializationFailure,
1282    ErrorCode::SnapshotNotFound,
1283    ErrorCode::PositionOutOfRange,
1284    ErrorCode::UnknownTopicId,
1285    ErrorCode::DuplicateBrokerRegistration,
1286    ErrorCode::BrokerIdNotRegistered,
1287    ErrorCode::InconsistentTopicId,
1288    ErrorCode::InconsistentClusterId,
1289    ErrorCode::TransactionalIdNotFound,
1290    ErrorCode::FetchSessionTopicIdError,
1291    ErrorCode::IneligibleReplica,
1292    ErrorCode::NewLeaderElected,
1293    ErrorCode::OffsetMovedToTieredStorage,
1294    ErrorCode::FencedMemberEpoch,
1295    ErrorCode::UnreleasedInstanceId,
1296    ErrorCode::UnsupportedAssignor,
1297    ErrorCode::StaleMemberEpoch,
1298    ErrorCode::MismatchedEndpointType,
1299    ErrorCode::UnsupportedEndpointType,
1300    ErrorCode::UnknownControllerId,
1301    ErrorCode::UnknownSubscriptionId,
1302    ErrorCode::TelemetryTooLarge,
1303    ErrorCode::InvalidRegistration,
1304    ErrorCode::TransactionAbortable,
1305    ErrorCode::InvalidRecordState,
1306    ErrorCode::ShareSessionNotFound,
1307    ErrorCode::InvalidShareSessionEpoch,
1308    ErrorCode::FencedStateEpoch,
1309    ErrorCode::InvalidVoterKey,
1310    ErrorCode::DuplicateVoter,
1311    ErrorCode::VoterNotFound,
1312    ErrorCode::InvalidRegularExpression,
1313    ErrorCode::RebootstrapRequired,
1314    ErrorCode::StreamsInvalidTopology,
1315    ErrorCode::StreamsInvalidTopologyEpoch,
1316    ErrorCode::StreamsTopologyFenced,
1317    ErrorCode::ShareSessionLimitReached,
1318];
1319
1320#[cfg(test)]
1321mod coordinator_retry_tests {
1322    use super::*;
1323
1324    /// The premise `RetryPolicy::coordinator_timeout` rests on.
1325    ///
1326    /// A longer budget buys nothing if `dispatch` short-circuits on
1327    /// `!error.retriable()` first, and the answer is delegated to
1328    /// `kafka-protocol` — so an upstream bump could silently take it away.
1329    #[test]
1330    fn the_coordinator_codes_are_retriable() {
1331        for code in [
1332            ErrorCode::NotCoordinator,
1333            ErrorCode::CoordinatorNotAvailable,
1334            ErrorCode::CoordinatorLoadInProgress,
1335        ] {
1336            assert!(code.retriable(), "{code} must be retriable");
1337            assert!(code.needs_coordinator_refresh(), "{code}");
1338        }
1339    }
1340}