apache/kafka · error · ConfigException
${ProducerConfig.DELIVERY_TIMEOUT_MS_CONFIG} should be equal
Error message
${ProducerConfig.DELIVERY_TIMEOUT_MS_CONFIG} should be equal to or larger than ${ProducerConfig.LINGER_MS_CONFIG} + ${ProducerConfig.REQUEST_TIMEOUT_MS_CONFIG} What it means
Thrown by configureDeliveryTimeout() when delivery.timeout.ms is less than linger.ms + request.timeout.ms AND the user explicitly set delivery.timeout.ms in their config. The producer enforces this invariant because a record must have at least enough delivery budget to wait out the linger window plus one request attempt. If the user did NOT override delivery.timeout.ms, the producer silently raises it to linger+request with a warn-level log instead of throwing.
Source
Thrown at clients/src/main/java/org/apache/kafka/clients/producer/KafkaProducer.java:638
default:
return Compression.of(type).build();
}
}
private static int lingerMs(ProducerConfig config) {
return (int) Math.min(config.getLong(ProducerConfig.LINGER_MS_CONFIG), Integer.MAX_VALUE);
}
private static int configureDeliveryTimeout(ProducerConfig config, Logger log) {
int deliveryTimeoutMs = config.getInt(ProducerConfig.DELIVERY_TIMEOUT_MS_CONFIG);
int lingerMs = lingerMs(config);
int requestTimeoutMs = config.getInt(ProducerConfig.REQUEST_TIMEOUT_MS_CONFIG);
int lingerAndRequestTimeoutMs = (int) Math.min((long) lingerMs + requestTimeoutMs, Integer.MAX_VALUE);
if (deliveryTimeoutMs < lingerAndRequestTimeoutMs) {
if (config.originals().containsKey(ProducerConfig.DELIVERY_TIMEOUT_MS_CONFIG)) {
// throw an exception if the user explicitly set an inconsistent value
throw new ConfigException(ProducerConfig.DELIVERY_TIMEOUT_MS_CONFIG
+ " should be equal to or larger than " + ProducerConfig.LINGER_MS_CONFIG
+ " + " + ProducerConfig.REQUEST_TIMEOUT_MS_CONFIG);
} else {
// override deliveryTimeoutMs default value to lingerMs + requestTimeoutMs for backward compatibility
deliveryTimeoutMs = lingerAndRequestTimeoutMs;
log.warn("{} should be equal to or larger than {} + {}. Setting it to {}.",
ProducerConfig.DELIVERY_TIMEOUT_MS_CONFIG, ProducerConfig.LINGER_MS_CONFIG,
ProducerConfig.REQUEST_TIMEOUT_MS_CONFIG, deliveryTimeoutMs);
}
}
return deliveryTimeoutMs;
}
private TransactionManager configureTransactionState(ProducerConfig config,
LogContext logContext) {
TransactionManager transactionManager = null;
if (config.getBoolean(ProducerConfig.ENABLE_IDEMPOTENCE_CONFIG)) {View on GitHub (pinned to c31c9215e1)
Solutions
- Raise delivery.timeout.ms to at least linger.ms + request.timeout.ms.
- Or lower request.timeout.ms and/or linger.ms to satisfy the existing delivery.timeout.ms.
- Prefer leaving delivery.timeout.ms unset so the producer auto-adjusts (it only throws on an explicit inconsistent value).
- Re-validate after every change to linger or request timeout — they are coupled.
Example fix
# before props.put(ProducerConfig.DELIVERY_TIMEOUT_MS_CONFIG, 20000); props.put(ProducerConfig.REQUEST_TIMEOUT_MS_CONFIG, 30000); new KafkaProducer<>(props); // -> ConfigException: 20000 < 0 + 30000 # after props.put(ProducerConfig.DELIVERY_TIMEOUT_MS_CONFIG, 45000); # >= linger + request props.put(ProducerConfig.REQUEST_TIMEOUT_MS_CONFIG, 30000); # or simply omit DELIVERY_TIMEOUT_MS_CONFIG and let the producer derive it.
Defensive patterns
Strategy: validation
Validate before calling
// delivery.timeout.ms must be >= linger.ms + request.timeout.ms when the user
// sets it explicitly; otherwise KafkaProducer throws ConfigException. Validate
// the invariant yourself before constructing.
import org.apache.kafka.clients.producer.ProducerConfig;
static void assertDeliveryTimeoutOk(java.util.Map<String,Object> p) {
long delivery = ((Number) p.getOrDefault(
ProducerConfig.DELIVERY_TIMEOUT_MS_CONFIG, 120000L)).longValue();
long linger = ((Number) p.getOrDefault(
ProducerConfig.LINGER_MS_CONFIG, 0L)).longValue();
long request = ((Number) p.getOrDefault(
ProducerConfig.REQUEST_TIMEOUT_MS_CONFIG, 30000L)).longValue();
if (delivery < linger + request) {
throw new org.apache.kafka.common.config.ConfigException(
ProducerConfig.DELIVERY_TIMEOUT_MS_CONFIG
+ " (" + delivery + ") must be >= "
+ ProducerConfig.LINGER_MS_CONFIG + " + "
+ ProducerConfig.REQUEST_TIMEOUT_MS_CONFIG
+ " (" + (linger + request) + ")");
}
}
// usage:
assertDeliveryTimeoutOk(props);
new KafkaProducer<>(props); Try / catch
try {
producer = new KafkaProducer<>(props);
} catch (org.apache.kafka.common.config.ConfigException e) {
if (e.getMessage().contains(ProducerConfig.DELIVERY_TIMEOUT_MS_CONFIG)) {
// bump delivery timeout to linger + request timeout + slack, then retry
props.put(ProducerConfig.DELIVERY_TIMEOUT_MS_CONFIG,
linger + request + 10_000);
producer = new KafkaProducer<>(props);
} else { throw e; }
} Prevention
- Set delivery.timeout.ms deliberately; don't let it default while you tune linger/request timeout.
- Centralize producer timing config in one builder that enforces the invariant.
- If you raise request.timeout.ms or linger.ms, recompute delivery.timeout.ms in the same change.
- Unit-test your config map with the validator above so regressions fail at build time.
When it happens
Trigger: Producer properties explicitly setting delivery.timeout.ms to a value smaller than linger.ms + request.timeout.ms (default: 120000 < 0+30000 is fine; reducing delivery.timeout.ms to e.g. 20000 while keeping request.timeout.ms=30000 trips it).
Common situations: Lowering delivery.timeout.ms to fail records faster for low-latency pipelines; raising request.timeout.ms for slow brokers without re-tuning delivery.timeout.ms; raising linger.ms for batching without bumping delivery timeout; inheriting config from another service whose linger was different.
Related errors
- The ${ProducerConfig.BUFFER_MEMORY_ALLOCATION_STRATEGY_INCRE
- Failed to construct kafka producer
- Timeout after waiting for {timeoutMillis} ms.
- client.rack must be provided if partitioner.rack.aware is en
- Transactional method invoked on a non-transactional producer
AI-assisted analysis of apache/kafka@c31c9215e1 (2026-08-03).
Data as JSON: /data/errors/c48af6851d776b46.json.
Report an issue: GitHub.