{"id":"c48af6851d776b46","repo":"apache/kafka","slug":"producerconfig-delivery-timeout-ms-config-shoul","errorCode":null,"errorMessage":"${ProducerConfig.DELIVERY_TIMEOUT_MS_CONFIG} should be equal to or larger than ${ProducerConfig.LINGER_MS_CONFIG} + ${ProducerConfig.REQUEST_TIMEOUT_MS_CONFIG}","messagePattern":"(.+?) should be equal to or larger than (.+?) \\+ (.+?)","errorType":"exception","errorClass":"ConfigException","httpStatus":null,"severity":"error","filePath":"clients/src/main/java/org/apache/kafka/clients/producer/KafkaProducer.java","lineNumber":638,"sourceCode":"            default:\n                return Compression.of(type).build();\n        }\n    }\n\n    private static int lingerMs(ProducerConfig config) {\n        return (int) Math.min(config.getLong(ProducerConfig.LINGER_MS_CONFIG), Integer.MAX_VALUE);\n    }\n\n    private static int configureDeliveryTimeout(ProducerConfig config, Logger log) {\n        int deliveryTimeoutMs = config.getInt(ProducerConfig.DELIVERY_TIMEOUT_MS_CONFIG);\n        int lingerMs = lingerMs(config);\n        int requestTimeoutMs = config.getInt(ProducerConfig.REQUEST_TIMEOUT_MS_CONFIG);\n        int lingerAndRequestTimeoutMs = (int) Math.min((long) lingerMs + requestTimeoutMs, Integer.MAX_VALUE);\n\n        if (deliveryTimeoutMs < lingerAndRequestTimeoutMs) {\n            if (config.originals().containsKey(ProducerConfig.DELIVERY_TIMEOUT_MS_CONFIG)) {\n                // throw an exception if the user explicitly set an inconsistent value\n                throw new ConfigException(ProducerConfig.DELIVERY_TIMEOUT_MS_CONFIG\n                    + \" should be equal to or larger than \" + ProducerConfig.LINGER_MS_CONFIG\n                    + \" + \" + ProducerConfig.REQUEST_TIMEOUT_MS_CONFIG);\n            } else {\n                // override deliveryTimeoutMs default value to lingerMs + requestTimeoutMs for backward compatibility\n                deliveryTimeoutMs = lingerAndRequestTimeoutMs;\n                log.warn(\"{} should be equal to or larger than {} + {}. Setting it to {}.\",\n                    ProducerConfig.DELIVERY_TIMEOUT_MS_CONFIG, ProducerConfig.LINGER_MS_CONFIG,\n                    ProducerConfig.REQUEST_TIMEOUT_MS_CONFIG, deliveryTimeoutMs);\n            }\n        }\n        return deliveryTimeoutMs;\n    }\n\n    private TransactionManager configureTransactionState(ProducerConfig config,\n                                                         LogContext logContext) {\n        TransactionManager transactionManager = null;\n\n        if (config.getBoolean(ProducerConfig.ENABLE_IDEMPOTENCE_CONFIG)) {","sourceCodeStart":620,"sourceCodeEnd":656,"githubUrl":"https://github.com/apache/kafka/blob/c31c9215e131f8c17e79f8901b48c13ee6aa8e7a/clients/src/main/java/org/apache/kafka/clients/producer/KafkaProducer.java#L620-L656","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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."],"exampleFix":"# before\nprops.put(ProducerConfig.DELIVERY_TIMEOUT_MS_CONFIG, 20000);\nprops.put(ProducerConfig.REQUEST_TIMEOUT_MS_CONFIG, 30000);\nnew KafkaProducer<>(props); // -> ConfigException: 20000 < 0 + 30000\n\n# after\nprops.put(ProducerConfig.DELIVERY_TIMEOUT_MS_CONFIG, 45000);  # >= linger + request\nprops.put(ProducerConfig.REQUEST_TIMEOUT_MS_CONFIG, 30000);\n# or simply omit DELIVERY_TIMEOUT_MS_CONFIG and let the producer derive it.","handlingStrategy":"validation","validationCode":"// delivery.timeout.ms must be >= linger.ms + request.timeout.ms when the user\n// sets it explicitly; otherwise KafkaProducer throws ConfigException. Validate\n// the invariant yourself before constructing.\nimport org.apache.kafka.clients.producer.ProducerConfig;\n\nstatic void assertDeliveryTimeoutOk(java.util.Map<String,Object> p) {\n    long delivery = ((Number) p.getOrDefault(\n            ProducerConfig.DELIVERY_TIMEOUT_MS_CONFIG, 120000L)).longValue();\n    long linger   = ((Number) p.getOrDefault(\n            ProducerConfig.LINGER_MS_CONFIG, 0L)).longValue();\n    long request  = ((Number) p.getOrDefault(\n            ProducerConfig.REQUEST_TIMEOUT_MS_CONFIG, 30000L)).longValue();\n    if (delivery < linger + request) {\n        throw new org.apache.kafka.common.config.ConfigException(\n            ProducerConfig.DELIVERY_TIMEOUT_MS_CONFIG\n            + \" (\" + delivery + \") must be >= \"\n            + ProducerConfig.LINGER_MS_CONFIG + \" + \"\n            + ProducerConfig.REQUEST_TIMEOUT_MS_CONFIG\n            + \" (\" + (linger + request) + \")\");\n    }\n}\n\n// usage:\nassertDeliveryTimeoutOk(props);\nnew KafkaProducer<>(props);","typeGuard":null,"tryCatchPattern":"try {\n    producer = new KafkaProducer<>(props);\n} catch (org.apache.kafka.common.config.ConfigException e) {\n    if (e.getMessage().contains(ProducerConfig.DELIVERY_TIMEOUT_MS_CONFIG)) {\n        // bump delivery timeout to linger + request timeout + slack, then retry\n        props.put(ProducerConfig.DELIVERY_TIMEOUT_MS_CONFIG,\n            linger + request + 10_000);\n        producer = new KafkaProducer<>(props);\n    } else { throw e; }\n}","preventionTips":["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."],"tags":["producer","config","timeouts","delivery"],"analyzedSha":"c31c9215e131f8c17e79f8901b48c13ee6aa8e7a","analyzedAt":"2026-08-03T12:34:05.770Z","schemaVersion":2}