{"record":{"id":"643bde47b42b1988","repo":"apache/pulsar","slug":"expire-message-by-timestamp-is-not-supported-for-n","errorCode":null,"errorMessage":"Expire message by timestamp is not supported for non-persistent topic.","messagePattern":"Expire message by timestamp is not supported for non-persistent topic\\.","errorType":"exception","errorClass":"java.lang.UnsupportedOperationException","httpStatus":null,"severity":"warning","filePath":"pulsar-broker/src/main/java/org/apache/pulsar/broker/service/nonpersistent/NonPersistentSubscription.java","lineNumber":498,"sourceCode":"            log.warn().attr(\"consumer\", consumer).log(\"Error removing consumer\");\n            future.completeExceptionally(e);\n        }\n        return future;\n    }\n\n    @Override\n    public List<Consumer> getConsumers() {\n        Dispatcher dispatcher = this.dispatcher;\n        if (dispatcher != null) {\n            return dispatcher.getConsumers();\n        } else {\n            return Collections.emptyList();\n        }\n    }\n\n    @Override\n    public boolean expireMessages(int messageTTLInSeconds) {\n        throw new UnsupportedOperationException(\"Expire message by timestamp is not supported for\"\n                + \" non-persistent topic.\");\n    }\n\n    @Override\n    public CompletableFuture<Boolean> expireMessagesAsync(int messageTTLInSeconds) {\n        return CompletableFuture.failedFuture(new UnsupportedOperationException(\"Expire message by timestamp is not\"\n                + \" supported for non-persistent topic.\"));\n    }\n\n    @Override\n    public boolean expireMessages(Position position) {\n        throw new UnsupportedOperationException(\"Expire message by position is not supported for\"\n                + \" non-persistent topic.\");\n    }\n\n    public NonPersistentSubscriptionStatsImpl getStats(GetStatsOptions getStatsOptions) {\n        NonPersistentSubscriptionStatsImpl subStats = new NonPersistentSubscriptionStatsImpl();\n        subStats.bytesOutCounter = bytesOutFromRemovedConsumers.longValue();","sourceCodeStart":480,"sourceCodeEnd":516,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-broker/src/main/java/org/apache/pulsar/broker/service/nonpersistent/NonPersistentSubscription.java#L480-L516","documentation":"NonPersistentSubscription.expireMessages(int messageTTLInSeconds) unconditionally throws UnsupportedOperationException because message expiration by timestamp requires persistent storage/cursors that non-persistent topics do not have.","triggerScenarios":"Calling subscription.expireMessages(messageTTLInSeconds) or admin/API paths that trigger TTL-based message expiry on a subscription of a non-persistent topic.","commonSituations":"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.","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"],"exampleFix":"// before\nsubscription.expireMessages(ttlSeconds);\n// after\nif (subscription.getTopic().isPersistentTopic()) {\n    subscription.expireMessages(ttlSeconds);\n}","handlingStrategy":"type-guard","validationCode":"if (!topicName.getPersistent()) {\n    // skip TTL expiry for non-persistent topics\n    return;\n}\nsubscription.expireMessages(ttlSeconds);","typeGuard":"boolean supportsTtlExpiry(Topic t) {\n    return t instanceof org.apache.pulsar.broker.service.persistent.PersistentTopic;\n}","tryCatchPattern":"try {\n    subscription.expireMessages(ttlSeconds);\n} catch (UnsupportedOperationException e) {\n    log.debug(\"TTL expiry unsupported for non-persistent topic\");\n}","preventionTips":["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"],"tags":["java","broker","non-persistent","ttl","unsupported-operation"],"backgroundTag":"operation-not-supported-on-non-persistent-topic","analyzedSha":"820761864ed8e2a7d2e52dd9763ad2ae117c1395","analyzedAt":"2026-09-06T00:14:20.138Z","contentChangedAt":"2026-09-06T00:14:20.138Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}