apache/pulsar · error · IllegalArgumentException
V1 topic names (with cluster component) are no longer suppor
Error message
V1 topic names (with cluster component) are no longer supported. Please use the V2 format: '<domain>://tenant/namespace/topic'. Got: ${completeTopicName} What it means
Pulsar V1 topic names embedded a cluster component: 'domain://cluster/tenant/namespace/topic' (4 path parts after '://'). The parser rejects this shape outright and asks callers to migrate to the V2 format 'domain://tenant/namespace/topic'. It is thrown from the TopicName constructor whenever a fully-qualified name splits into 4 parts after the scheme.
Source
Thrown at pulsar-common/src/main/java/org/apache/pulsar/common/naming/TopicName.java:187
} else {
throw new IllegalArgumentException(
"Invalid short topic name '" + completeTopicName + "', it should be in the format of "
+ "<tenant>/<namespace>/<topic> or <topic>");
}
this.segmentRange = null;
this.segmentId = -1;
this.completeTopicName = domain.name() + "://" + tenant + "/" + namespacePortion + "/" + localName;
} else {
this.domain = TopicDomain.getEnum(completeTopicName.substring(0, index));
// Scalable topic domains (topic://, segment://) only support the new format
// and local names may contain '/', so use limit(3) to keep the rest as localName.
boolean isScalableDomain = this.domain == TopicDomain.topic
|| this.domain == TopicDomain.segment;
int splitLimit = isScalableDomain ? 3 : 4;
List<String> parts = splitBySlash(completeTopicName.substring(index + "://".length()),
splitLimit);
if (parts.size() == 4) {
throw new IllegalArgumentException(
"V1 topic names (with cluster component) are no longer supported. "
+ "Please use the V2 format: '<domain>://tenant/namespace/topic'. Got: "
+ completeTopicName);
} else if (parts.size() != 3) {
throw new IllegalArgumentException("Invalid topic name " + completeTopicName);
}
this.tenant = parts.get(0);
this.namespacePortion = parts.get(1);
String rawLocalName = parts.get(2);
// For segment:// domains, split local name into parent topic name + descriptor
if (this.domain == TopicDomain.segment) {
int lastSlash = rawLocalName.lastIndexOf('/');
if (lastSlash <= 0) {
throw new IllegalArgumentException(
"Invalid segment topic name: local name must contain"
+ " '<parent-topic>/<hashStart>-<hashEnd>-<segmentId>'. Got: "
+ completeTopicName);View on GitHub (pinned to 820761864e)
Solutions
- Remove the cluster component: 'persistent://clusterX/tenant/ns/topic' -> 'persistent://tenant/ns/topic'
- Re-derive topic names from current cluster config instead of legacy stored values
- If reading legacy data, map old names to V2 names with a migration/shim before calling TopicName.get
Example fix
// before
TopicName topic = TopicName.get("persistent://us-west/my-tenant/my-ns/my-topic");
// after
TopicName topic = TopicName.get("persistent://my-tenant/my-ns/my-topic"); Defensive patterns
Strategy: validation
Validate before calling
static String stripV1Cluster(String topic) {
java.util.regex.Matcher m = java.util.regex.Pattern
.compile("^([a-z]+)://[^/]+/([^/]+/[^/]+/[^/]+)$").matcher(topic);
if (m.matches()) {
throw new IllegalArgumentException("V1 topic name not supported: " + topic);
}
return topic;
} Type guard
static boolean isV2TopicName(String name) {
java.util.regex.Matcher m = java.util.regex.Pattern
.compile("^[a-z]+://[^/]+/[^/]+/[^/]+$").matcher(name == null ? "" : name);
return m.matches();
} Try / catch
try {
TopicName tn = TopicName.get(topic);
} catch (IllegalArgumentException e) {
if (e.getMessage().contains("V1 topic names")) {
topic = migrateV1ToV2(topic); // drop cluster component, retry once
TopicName tn = TopicName.get(topic);
} else throw e;
} Prevention
- Search configs/scripts for legacy 'domain://cluster/tenant/ns/topic' patterns after upgrading from Pulsar 1.x
- Store topic names in the V2 form going forward
- Add a startup check that rejects V1-format names in configuration
- Regenerate topic URLs from current cluster metadata rather than copying old ones
When it happens
Trigger: Calling TopicName.get('persistent://clusterX/tenant/ns/topic') or any API that resolves a topic name containing a legacy cluster segment after '://'.
Common situations: Migrating from very old Pulsar clusters (pre-2.x V1 naming); configs, scripts, or bookmarked topic URLs copied from an old deployment; broker/standalone configs carried over across a version upgrade.
Related errors
- Invalid short topic name '${completeTopicName}', it should b
- Invalid topic name ${completeTopicName}
- Invalid segment topic name: local name must contain '<parent
- Invalid segment descriptor: expected '<hexStart>-<hexEnd>-<s
- ResourceGroupCreate: Invalid null ResourceGroup config
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/bdf9a5545a8d2705.
Report an issue: GitHub.