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

  1. Keep the input topic set identical to the existing function's set in the update.
  2. To change inputs, delete and recreate the function with the desired input topics.
  3. 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

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


AI-assisted analysis of apache/pulsar@820761864e (2026-09-06). Data as JSON: /api/errors/7a7d3ce58e4762c8. Report an issue: GitHub.