apache/pulsar · error · IllegalArgumentException
AutoAck cannot be altered
Error message
AutoAck cannot be altered
What it means
FunctionConfigUtils.validateUpdate rejects changing the autoAck setting on an existing function: autoAck is immutable after creation because it changes acknowledgement semantics for in-flight messages.
Source
Thrown at pulsar-functions/utils/src/main/java/org/apache/pulsar/functions/utils/FunctionConfigUtils.java:1093
throw new IllegalArgumentException("Retain Key Ordering cannot be altered");
}
if (!StringUtils.isEmpty(newConfig.getOutput())) {
mergedConfig.setOutput(newConfig.getOutput());
}
if (newConfig.getUserConfig() != null) {
mergedConfig.setUserConfig(newConfig.getUserConfig());
}
if (newConfig.getSecrets() != null) {
mergedConfig.setSecrets(newConfig.getSecrets());
}
if (newConfig.getRuntime() != null && !newConfig.getRuntime().equals(existingConfig.getRuntime())) {
throw new IllegalArgumentException("Runtime cannot be altered");
}
@SuppressWarnings("deprecation")
boolean autoAckChanged = newConfig.getAutoAck() != null
&& !newConfig.getAutoAck().equals(existingConfig.getAutoAck());
if (autoAckChanged) {
throw new IllegalArgumentException("AutoAck cannot be altered");
}
if (newConfig.getMaxMessageRetries() != null) {
mergedConfig.setMaxMessageRetries(newConfig.getMaxMessageRetries());
}
if (!StringUtils.isEmpty(newConfig.getDeadLetterTopic())) {
mergedConfig.setDeadLetterTopic(newConfig.getDeadLetterTopic());
}
if (!StringUtils.isEmpty(newConfig.getSubName()) && !newConfig.getSubName()
.equals(existingConfig.getSubName())) {
throw new IllegalArgumentException("Subscription Name cannot be altered");
}
if (newConfig.getParallelism() != null) {
mergedConfig.setParallelism(newConfig.getParallelism());
}
if (newConfig.getResources() != null) {
mergedConfig
.setResources(ResourceConfigUtils.merge(existingConfig.getResources(), newConfig.getResources()));
}View on GitHub (pinned to 820761864e)
Solutions
- Keep autoAck unchanged in the update request
- Recreate the function if autoAck must change
Example fix
// before update.setAutoAck(false); // deprecated + differs -> thrown // after update.setAutoAck(null); // leave deprecated field unset
Defensive patterns
Strategy: validation
Validate before calling
if (update.getAutoAck() != null) {
update.setAutoAck(null); // deprecated field; leave unset on updates
} Try / catch
try {
admin.functions().updateFunction(update, pkgFile);
} catch (IllegalArgumentException e) {
if (e.getMessage().contains("AutoAck")) { /* clear autoAck and retry */ }
else throw e;
} Prevention
- Stop using the deprecated autoAck field entirely.
- Purge autoAck from stored/template configs.
- Migrate tooling to current FunctionConfig fields.
When it happens
Trigger: Updating a function where getAutoAck() is non-null and differs from the existing config's autoAck value.
Common situations: Old configs or legacy tooling that still set autoAck; SDK clients carrying autoAck=true/false defaults from older Pulsar versions into update requests.
Related errors
- Retain Ordering cannot be altered
- Retain Key Ordering cannot be altered
- Runtime cannot be altered
- Subscription Name cannot be altered
- You must specify either a Fully Qualified Function Name (FQF
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/68f287e7078731d4.
Report an issue: GitHub.