apache/pulsar · warning · java.lang.UnsupportedOperationException
Expire message by timestamp is not supported for non-persist
Error message
Expire message by timestamp is not supported for non-persistent topic.
What it means
NonPersistentSubscription.expireMessages(int messageTTLInSeconds) unconditionally throws UnsupportedOperationException because message expiration by timestamp requires persistent storage/cursors that non-persistent topics do not have.
Source
Thrown at pulsar-broker/src/main/java/org/apache/pulsar/broker/service/nonpersistent/NonPersistentSubscription.java:498
log.warn().attr("consumer", consumer).log("Error removing consumer");
future.completeExceptionally(e);
}
return future;
}
@Override
public List<Consumer> getConsumers() {
Dispatcher dispatcher = this.dispatcher;
if (dispatcher != null) {
return dispatcher.getConsumers();
} else {
return Collections.emptyList();
}
}
@Override
public boolean expireMessages(int messageTTLInSeconds) {
throw new UnsupportedOperationException("Expire message by timestamp is not supported for"
+ " non-persistent topic.");
}
@Override
public CompletableFuture<Boolean> expireMessagesAsync(int messageTTLInSeconds) {
return CompletableFuture.failedFuture(new UnsupportedOperationException("Expire message by timestamp is not"
+ " supported for non-persistent topic."));
}
@Override
public boolean expireMessages(Position position) {
throw new UnsupportedOperationException("Expire message by position is not supported for"
+ " non-persistent topic.");
}
public NonPersistentSubscriptionStatsImpl getStats(GetStatsOptions getStatsOptions) {
NonPersistentSubscriptionStatsImpl subStats = new NonPersistentSubscriptionStatsImpl();
subStats.bytesOutCounter = bytesOutFromRemovedConsumers.longValue();View on GitHub (pinned to 820761864e)
Solutions
- Use persistent topics if message TTL/expiry is required
- Avoid calling expireMessages on non-persistent subscriptions; rely on consumer-side message TTL checks instead
- Guard admin automation/scripts to skip non-persistent topics for TTL operations
- Catch UnsupportedOperationException and treat as a no-op for non-persistent topics
Example fix
// before
subscription.expireMessages(ttlSeconds);
// after
if (subscription.getTopic().isPersistentTopic()) {
subscription.expireMessages(ttlSeconds);
} Defensive patterns
Strategy: type-guard
Validate before calling
if (!topicName.getPersistent()) {
// skip TTL expiry for non-persistent topics
return;
}
subscription.expireMessages(ttlSeconds); Type guard
boolean supportsTtlExpiry(Topic t) {
return t instanceof org.apache.pulsar.broker.service.persistent.PersistentTopic;
} Try / catch
try {
subscription.expireMessages(ttlSeconds);
} catch (UnsupportedOperationException e) {
log.debug("TTL expiry unsupported for non-persistent topic");
} Prevention
- Filter non-persistent topics out of TTL automation
- Check topic type via admin API before expiry calls
- Enable TTL only on namespaces with persistent topics
When it happens
Trigger: Calling subscription.expireMessages(messageTTLInSeconds) or admin/API paths that trigger TTL-based message expiry on a subscription of a non-persistent topic.
Common situations: Applying topic-level TTL policies (ttlDurationDefault / namespace TTL) to non-persistent topics; admin CLI/REST expire-messages call against a non-persistent topic; generic admin tooling that assumes all topics support expiry.
Related errors
- Expire message by position is not supported for non-persiste
- PublishTxnMessage is not supported by non-persistent topic
- Failed to add schema to an active topic with empty(BYTES) sc
- Package Management Service is not enabled in the broker.
- ${key} already exists in the dynamicConfigurationMap
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/643bde47b42b1988.
Report an issue: GitHub.