apache/pulsar · error · UnsupportedOperationException
V5 does not support non-persistent:// topics: + topic
Error message
V5 does not support non-persistent:// topics: + topic
What it means
V5Utils.parseScalableTopicInput validates topic names before the V5 SDK uses them. Scalable topics are always backed by managed ledgers (persistent storage), and the V5 client has no code path for non-persistent topics, so any topic with the non-persistent:// domain is rejected with UnsupportedOperationException.
Source
Thrown at pulsar-client-v5/src/main/java/org/apache/pulsar/client/impl/v5/V5Utils.java:56
* layout (regular topic that has not yet been migrated):
* <ul>
* <li>{@code topic://tenant/ns/x} — explicitly scalable.</li>
* <li>{@code persistent://tenant/ns/x} — regular topic; if it has been migrated the
* broker promotes it to its {@code topic://} identity and returns the real DAG,
* otherwise it returns a synthetic layout that wraps the existing partitions.</li>
* <li>Short forms ({@code my-topic} or {@code tenant/ns/my-topic}) — normalised by
* {@link TopicName#get(String)} to {@code persistent://public/default/...} or
* {@code persistent://tenant/ns/...}; treated like any other persistent input.</li>
* </ul>
*
* <p>Rejects {@code non-persistent://} with {@link UnsupportedOperationException}:
* scalable topics are always backed by managed ledgers, and the V5 SDK has no path
* to a non-persistent topic.
*/
static TopicName parseScalableTopicInput(String topic) {
TopicName tn = TopicName.get(topic);
if (tn.getDomain() == TopicDomain.non_persistent) {
throw new UnsupportedOperationException(
"V5 does not support non-persistent:// topics: " + topic);
}
return tn;
}
}
View on GitHub (pinned to 820761864e)
Solutions
- Change the topic URL to use the persistent:// domain (scalable/V5 topics require managed-ledger-backed persistent topics).
- If the topic truly must be non-persistent, keep using the classic (non-V5) Pulsar client, which supports non-persistent topics.
- If the domain is constructed dynamically, validate/normalize it before passing the topic to V5 APIs, defaulting to persistent://.
Example fix
// before String topic = "non-persistent://public/default/events"; client.newProducer(V5Config).topic(topic).create(); // after String topic = "persistent://public/default/events"; client.newProducer(V5Config).topic(topic).create();
Defensive patterns
Strategy: validation
Validate before calling
if (topic.startsWith("non-persistent://")) {
throw new IllegalArgumentException("V5 SDK requires persistent topics, got: " + topic);
} Prevention
- Normalize all topic URLs to persistent:// before constructing V5 clients.
- Centralize topic-name construction in one helper that enforces the persistent domain.
- Document that non-persistent topics are unsupported in the V5 scalable-topic path.
When it happens
Trigger: Calling a V5 SDK API that internally invokes parseScalableTopicInput with a topic string whose domain is 'non-persistent://', e.g. building a producer/consumer/reader on 'non-persistent://tenant/ns/my-topic' via the scalable-topic path.
Common situations: Migrating existing Pulsar clients that used non-persistent topics to the V5 SDK; copy-pasting topic URLs that keep the non-persistent:// prefix; configuration where the topic domain is built dynamically and defaults to non_persistent.
Related errors
- unknown auth provider: %s
- Go instance current not support EFFECTIVELY_ONCE processing
- Message retries not yet supported in python
- Unable to convert digest type ${digestType}
- Timeout during mark-delete operation
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/59f1109a69679ba4.
Report an issue: GitHub.