apache/pulsar · error · IllegalArgumentException
Input Topics cannot be altered
Error message
Input Topics cannot be altered
What it means
Input topic subscriptions of a function are immutable across updates: you cannot add or remove input topics. This error is thrown when newConfig.getInputSpecs() contains a topic name that is not present in existingConfig.getInputSpecs().
Source
Thrown at pulsar-functions/utils/src/main/java/org/apache/pulsar/functions/utils/FunctionConfigUtils.java:1045
ConsumerConfig.builder()
.serdeClassName(serdeClassName)
.isRegexPattern(false)
.build());
});
}
if (newConfig.getCustomSchemaInputs() != null) {
newConfig.getCustomSchemaInputs().forEach((topicName, schemaClassname) -> {
newConfig.getInputSpecs().put(topicName,
ConsumerConfig.builder()
.schemaType(schemaClassname)
.isRegexPattern(false)
.build());
});
}
if (!newConfig.getInputSpecs().isEmpty()) {
newConfig.getInputSpecs().forEach((topicName, consumerConfig) -> {
if (!existingConfig.getInputSpecs().containsKey(topicName)) {
throw new IllegalArgumentException("Input Topics cannot be altered");
}
if (consumerConfig.isRegexPattern() != existingConfig.getInputSpecs().get(topicName).isRegexPattern()) {
throw new IllegalArgumentException(
"isRegexPattern for input topic " + topicName + " cannot be altered");
}
mergedConfig.getInputSpecs().put(topicName, consumerConfig);
});
}
if (!StringUtils.isEmpty(newConfig.getOutputSerdeClassName()) && !newConfig.getOutputSerdeClassName()
.equals(existingConfig.getOutputSerdeClassName())) {
throw new IllegalArgumentException("Output Serde mismatch");
}
if (!StringUtils.isEmpty(newConfig.getOutputSchemaType()) && !newConfig.getOutputSchemaType()
.equals(existingConfig.getOutputSchemaType())) {
throw new IllegalArgumentException("Output Schema mismatch");
}
if (!StringUtils.isEmpty(newConfig.getLogTopic())) {
mergedConfig.setLogTopic(newConfig.getLogTopic());View on GitHub (pinned to 820761864e)
Solutions
- Keep the input topic set identical to the existing function's set in the update.
- To change inputs, delete and recreate the function with the desired input topics.
- Note removing topics alone does not throw here, but adding a new one does — ensure the merged set matches existing keys.
Example fix
// before
newConfig.addToInputSpecs("persistent://public/default/new-topic", consumerConfig); // not in existing
// after
// recreate function instead:
// 1) delete existing function 2) create with full new inputSpecs Defensive patterns
Strategy: validation
Validate before calling
Set<String> existingTopics = existingConfig.getInputSpecs().keySet();
for (String topic : newConfig.getInputSpecs().keySet()) {
if (!existingTopics.contains(topic)) {
throw new IllegalArgumentException("Cannot add input topic " + topic + " on update; recreate the function");
}
} Type guard
boolean canApplyInputSpecs(FunctionConfig existing, FunctionConfig updated) {
return existing.getInputSpecs().keySet().containsAll(updated.getInputSpecs().keySet());
} Try / catch
try {
merged = FunctionConfigUtils.validateUpdate(existing, updated);
} catch (IllegalArgumentException e) {
if (e.getMessage().equals("Input Topics cannot be altered")) {
throw new IllegalStateException("Recreate the function to change input topics", e);
} else { throw e; }
} Prevention
- Treat input topic sets as immutable per function instance.
- Plan topic additions as delete+create deployments.
- Diff new vs existing inputSpecs in CI before issuing updates.
When it happens
Trigger: Updating a function while adding a new input topic to inputSpecs (or inputTopics) that the function was not originally created with.
Common situations: Widening a function's source topics after deployment; switching a function from one input topic to another in a single update; config drift between environments where input lists differ.
Related errors
- Tenants differ
- Namespaces differ
- Function Names differ
- isRegexPattern for input topic
- Output Serde mismatch
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/7a7d3ce58e4762c8.
Report an issue: GitHub.