apache/kafka · error · ConfigException
Invalid configuration value for 'acks': {acksString}
Error message
Invalid configuration value for 'acks': {acksString} What it means
Thrown by ProducerConfig.parseAcks when the configured value for `acks` is neither the literal string 'all' (case-insensitive) nor a valid 16-bit signed short. parseAcks trims the input, maps 'all' to '-1', and otherwise calls Short.parseShort; any non-numeric or out-of-range input raises NumberFormatException which is converted to this ConfigException. Note the message echoes only the raw string, not which config key it came from.
Source
Thrown at clients/src/main/java/org/apache/kafka/clients/producer/ProducerConfig.java:709
// In standard Kafka transactions, the broker enforces transaction.timeout.ms and aborts any
// transaction that isn't completed in time. With two-phase commit (2PC), an external coordinator
// decides when to finalize, so broker-side timeouts don't apply. Disallow using both.
boolean enable2PC = this.getBoolean(TRANSACTION_TWO_PHASE_COMMIT_ENABLE_CONFIG);
boolean userConfiguredTransactionTimeout = originalConfigs.containsKey(TRANSACTION_TIMEOUT_CONFIG);
if (enable2PC && userConfiguredTransactionTimeout) {
throw new ConfigException(
"Cannot set " + ProducerConfig.TRANSACTION_TIMEOUT_CONFIG +
" when " + ProducerConfig.TRANSACTION_TWO_PHASE_COMMIT_ENABLE_CONFIG +
" is set to true. Transactions will not expire with two-phase commit enabled."
);
}
}
private static String parseAcks(String acksString) {
try {
return acksString.trim().equalsIgnoreCase("all") ? "-1" : Short.parseShort(acksString.trim()) + "";
} catch (NumberFormatException e) {
throw new ConfigException("Invalid configuration value for 'acks': " + acksString);
}
}
static Map<String, Object> appendSerializerToConfig(Map<String, Object> configs,
Serializer<?> keySerializer,
Serializer<?> valueSerializer) {
// validate serializer configuration, if the passed serializer instance is null, the user must explicitly set a valid serializer configuration value
Map<String, Object> newConfigs = new HashMap<>(configs);
if (keySerializer != null)
newConfigs.put(KEY_SERIALIZER_CLASS_CONFIG, keySerializer.getClass());
else if (newConfigs.get(KEY_SERIALIZER_CLASS_CONFIG) == null)
throw new ConfigException(KEY_SERIALIZER_CLASS_CONFIG, null, "must be non-null.");
if (valueSerializer != null)
newConfigs.put(VALUE_SERIALIZER_CLASS_CONFIG, valueSerializer.getClass());
else if (newConfigs.get(VALUE_SERIALIZER_CLASS_CONFIG) == null)
throw new ConfigException(VALUE_SERIALIZER_CLASS_CONFIG, null, "must be non-null.");
return newConfigs;
}View on GitHub (pinned to c31c9215e1)
Solutions
- Set `acks` to one of: `all`, `-1`, `0`, or `1` as a string.
- If the value is supplied dynamically, validate it is one of those before constructing the producer.
- Check environment-variable substitution and YAML/JSON serialization layers that may have coerced the value.
Example fix
// before
props.put("acks", "any");
// after
props.put("acks", "all"); Defensive patterns
Strategy: type-guard
Validate before calling
// Normalise and validate acks BEFORE handing the config to KafkaProducer.
static String normalizeAcks(Object acksRaw) {
String s = String.valueOf(acksRaw).trim();
if (s.equalsIgnoreCase("all")) return "all";
try {
short v = Short.parseShort(s);
if (v < -1) throw new IllegalArgumentException("acks too small: " + s);
return Short.toString(v);
} catch (NumberFormatException e) {
throw new IllegalArgumentException("Invalid acks value: " + acksRaw);
}
}
// Caller:
cfg.put(ProducerConfig.ACKS_CONFIG, normalizeAcks(cfg.get(ProducerConfig.ACKS_CONFIG))); Type guard
// Narrow an arbitrary config value to a proven-valid acks string.
static final java.util.regex.Pattern ACKS = java.util.regex.Pattern.compile("^(all|-1|\\d+)$", java.util.regex.Pattern.CASE_INSENSITIVE);
static boolean isAcksValue(Object o) {
if (o == null) return false;
String s = String.valueOf(o).trim();
if (!ACKS.matcher(s).matches()) return false;
try { Short.parseShort(s.equalsIgnoreCase("all") ? "-1" : s); return true; }
catch (NumberFormatException e) { return false; }
}
// Use: assert isAcksValue(cfg.get(ProducerConfig.ACKS_CONFIG)); Try / catch
try {
producer = new KafkaProducer<>(cfg);
} catch (ConfigException e) {
if (e.getMessage().contains("'acks'")) {
cfg.put(ProducerConfig.ACKS_CONFIG, "all"); // safe default
producer = new KafkaProducer<>(cfg);
} else throw e;
} Prevention
- Valid acks values are 'all' (==-1), 0, 1, or a positive replica count — nothing else parses.
- Don't compute acks from free-form env vars without a guard; a trailing space or typo triggers this.
- Centralize acks normalization so Integer/Short/String forms all converge to one canonical value.
When it happens
Trigger: Calling `props.put("acks", "any")`, `acks=-30000` (out of short range), `acks=true`, or any non-numeric token other than 'all'. Triggered during KafkaProducer construction via postProcessAndValidateIdotenceConfigs -> parseAcks at ProducerConfig.java:707.
Common situations: Misspelling 'all' as 'ALL' is fine (case-insensitive) but 'any', 'yes', 'full', or 'true' are common typos; loading acks from an environment variable or YAML where it was serialized as a non-string type; passing a Boolean instead of a String.
Related errors
- Topic collection to subscribe to cannot contain null or empt
- The configured group.id should not be an empty string or whi
- Topic collection to subscribe to cannot contain null or empt
- Invalid value `{}` for configuration {}. The value must eith
- Invalid producer ID and epoch values: {producerId}:{epoch}.
AI-assisted analysis of apache/kafka@c31c9215e1 (2026-08-03).
Data as JSON: /data/errors/8e70b6e1bacc6f46.json.
Report an issue: GitHub.