apache/pulsar · error · IllegalArgumentException
isRegexPattern for input topic cannot be altered
Error message
isRegexPattern for input topic cannot be altered
What it means
Thrown by SinkConfigUtils.validateUpdate when a known input topic's ConsumerConfig.isRegexPattern() flag differs between the existing and new config. Whether a topic is consumed as a regex pattern is fixed at creation time.
Source
Thrown at pulsar-functions/utils/src/main/java/org/apache/pulsar/functions/utils/SinkConfigUtils.java:677
});
}
if (newConfig.getTopicToSchemaType() != null) {
newConfig.getTopicToSchemaType().forEach((topicName, schemaClassname) -> {
newConfig.getInputSpecs().put(topicName,
ConsumerConfig.builder()
.schemaType(schemaClassname)
.isRegexPattern(false)
.build());
});
}
if (!newConfig.getInputSpecs().isEmpty()) {
SinkConfig finalMergedConfig = mergedConfig;
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");
}
finalMergedConfig.getInputSpecs().put(topicName, consumerConfig);
});
}
if (newConfig.getProcessingGuarantees() != null && !newConfig.getProcessingGuarantees()
.equals(existingConfig.getProcessingGuarantees())) {
throw new IllegalArgumentException("Processing Guarantees cannot be altered");
}
if (newConfig.getConfigs() != null) {
mergedConfig.setConfigs(newConfig.getConfigs());
}
if (newConfig.getSecrets() != null) {
mergedConfig.setSecrets(newConfig.getSecrets());
}
if (newConfig.getParallelism() != null) {
mergedConfig.setParallelism(newConfig.getParallelism());
}View on GitHub (pinned to 820761864e)
Solutions
- Keep isRegexPattern for each input topic identical to the existing sink's value
- To change a topic between regex and plain, delete and recreate the sink
- Compare each ConsumerConfig.isRegexPattern() with the deployed config before updating
Example fix
// before
cc.setRegexPattern(false); // existing sink had true
sinkConfig.getInputSpecs().put("persistent://public/default/.*", cc);
admin.sinks().updateSink(tenant, namespace, sinkConfig, null);
// after
cc.setRegexPattern(true); // match existing
sinkConfig.getInputSpecs().put("persistent://public/default/.*", cc);
admin.sinks().updateSink(tenant, namespace, sinkConfig, null); Defensive patterns
Strategy: validation
Validate before calling
newCfg.getInputSpecs().forEach((topic, cc) -> {
ConsumerConfig old = existing.getInputSpecs().get(topic);
if (old != null && cc.isRegexPattern() != old.isRegexPattern()) {
throw new IllegalArgumentException("isRegexPattern mismatch for " + topic);
}
}); Try / catch
try {
admin.sinks().updateSink(tenant, namespace, cfg, null);
} catch (IllegalArgumentException e) {
if (e.getMessage().contains("isRegexPattern")) { /* fix regex flag to match existing */ }
else throw e;
} Prevention
- Preserve isRegexPattern exactly as deployed for each topic
- When rewriting topic strings, keep their regex/plain classification
- Check deployed ConsumerConfig values before updating
When it happens
Trigger: Updating a sink whose inputSpecs entry for an existing topic flips isRegexPattern from true to false or vice versa; passing a plain topic name where the sink was created with a regex topic (or the reverse).
Common situations: Config migration changes topic declarations from regex 'persistent://public/default/.*' to explicit names; a serializer/tool rewrites topics and toggles the regex flag.
Related errors
- Sink Names differ
- Subscription Name cannot be altered
- Input Topics cannot be altered
- Processing Guarantees cannot be altered
- Retain Ordering cannot be altered
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/a76da524300c2f46.
Report an issue: GitHub.