{"id":"8e7ffe81567fa844","repo":"apache/kafka","slug":"must-set-acks-to-all-in-order-to-use-the-idempoten","errorCode":null,"errorMessage":"Must set acks to all in order to use the idempotent producer. Otherwise we cannot guarantee idempotence.","messagePattern":"Must set acks to all in order to use the idempotent producer\\. Otherwise we cannot guarantee idempotence\\.","errorType":"validation","errorClass":"ConfigException","httpStatus":null,"severity":"error","filePath":"clients/src/main/java/org/apache/kafka/clients/producer/ProducerConfig.java","lineNumber":665,"sourceCode":"        final boolean userConfiguredIdempotence = this.originals().containsKey(ENABLE_IDEMPOTENCE_CONFIG);\n        boolean idempotenceEnabled = this.getBoolean(ENABLE_IDEMPOTENCE_CONFIG);\n        boolean shouldDisableIdempotence = false;\n\n        // For idempotence producers, values for `retries` and `acks` and `max.in.flight.requests.per.connection` need validation\n        if (idempotenceEnabled) {\n            final int retries = this.getInt(RETRIES_CONFIG);\n            if (retries == 0) {\n                if (userConfiguredIdempotence) {\n                    throw new ConfigException(\"Must set \" + RETRIES_CONFIG + \" to non-zero when using the idempotent producer.\");\n                }\n                log.info(\"Idempotence will be disabled because {} is set to 0.\", RETRIES_CONFIG);\n                shouldDisableIdempotence = true;\n            }\n\n            final short acks = Short.parseShort(acksStr);\n            if (acks != (short) -1) {\n                if (userConfiguredIdempotence) {\n                    throw new ConfigException(\"Must set \" + ACKS_CONFIG + \" to all in order to use the idempotent \" +\n                        \"producer. Otherwise we cannot guarantee idempotence.\");\n                }\n                log.info(\"Idempotence will be disabled because {} is set to {}, not set to 'all'.\", ACKS_CONFIG, acks);\n                shouldDisableIdempotence = true;\n            }\n\n            final int inFlightConnection = this.getInt(MAX_IN_FLIGHT_REQUESTS_PER_CONNECTION);\n            if (MAX_IN_FLIGHT_REQUESTS_PER_CONNECTION_FOR_IDEMPOTENCE < inFlightConnection) {\n                throw new ConfigException(\"To use the idempotent producer, \" + MAX_IN_FLIGHT_REQUESTS_PER_CONNECTION +\n                                          \" must be set to at most 5. Current value is \" + inFlightConnection + \".\");\n            }\n        }\n\n        if (shouldDisableIdempotence) {\n            configs.put(ENABLE_IDEMPOTENCE_CONFIG, false);\n            idempotenceEnabled = false;\n        }\n","sourceCodeStart":647,"sourceCodeEnd":683,"githubUrl":"https://github.com/apache/kafka/blob/c31c9215e131f8c17e79f8901b48c13ee6aa8e7a/clients/src/main/java/org/apache/kafka/clients/producer/ProducerConfig.java#L647-L683","documentation":"Thrown by ProducerConfig.postProcessAndValidateIdempotenceConfigs when the user explicitly enables idempotence but sets acks to anything other than 'all' (-1). Idempotent delivery requires full ISR acks so the broker can durably assign and advance the producer's sequence numbers; weaker ack levels would let a successful-but-unreplicated write become indistinguishable from a failed one and break the dedup window. As with retries, if idempotence was defaulted rather than explicitly requested it is silently disabled instead.","triggerScenarios":"User originals contain `enable.idempotence=true` together with `acks=0`, `acks=1`, or `acks=any-other-than-all-or--1`. The check at ProducerConfig.java:663 fires after parseAcks normalizes 'all' to '-1'.","commonSituations":"Inheriting a latency-tuning config that pinned `acks=1` for throughput and then turning on idempotence for exactly-once; or setting `acks=0` for fire-and-forget and forgetting it conflicts with the idempotent/transactional producer.","solutions":["Set `acks=all` (equivalently `acks=-1`) when enabling idempotence.","Remove the explicit `acks` override so the idempotent producer's default of 'all' applies.","If the lower acks level is genuinely desired, disable idempotence and do not set a transactional.id."],"exampleFix":"// before\nprops.put(\"enable.idempotence\", \"true\");\nprops.put(\"acks\", \"1\");\n\n// after\nprops.put(\"enable.idempotence\", \"true\");\nprops.put(\"acks\", \"all\");","handlingStrategy":"validation","validationCode":"// Ensure acks is 'all' (or -1) when idempotence is on, BEFORE constructing.\nboolean idempotenceEnabled = Boolean.TRUE.equals(cfg.get(ProducerConfig.ENABLE_IDEMPOTENCE_CONFIG));\nObject acksRaw = cfg.getOrDefault(ProducerConfig.ACKS_CONFIG, \"all\");\nString acks = String.valueOf(acksRaw).trim();\nboolean acksAll = acks.equalsIgnoreCase(\"all\") || \"-1\".equals(acks);\nif (idempotenceEnabled && !acksAll) {\n    throw new IllegalStateException(\"acks must be 'all' when enable.idempotence=true\");\n}\n// Or just force it:\nif (idempotenceEnabled) cfg.put(ProducerConfig.ACKS_CONFIG, \"all\");","typeGuard":null,"tryCatchPattern":"try {\n    producer = new KafkaProducer<>(cfg);\n} catch (ConfigException e) {\n    if (e.getMessage().contains(\"acks\")) {\n        cfg.put(ProducerConfig.ACKS_CONFIG, \"all\");\n        producer = new KafkaProducer<>(cfg);\n    } else throw e;\n}","preventionTips":["Idempotence requires acks=all; make it the default in your config builder whenever idempotence is on.","Don't mix a 'fast' acks=0/1 profile with idempotence — they are mutually exclusive guarantees.","Document the acks/idempotence coupling wherever producer config is exposed to operators."],"tags":["kafka","producer","configuration","idempotence","durability"],"analyzedSha":"c31c9215e131f8c17e79f8901b48c13ee6aa8e7a","analyzedAt":"2026-08-03T12:34:05.770Z","schemaVersion":2}