apache/pulsar · warning · java.lang.UnsupportedOperationException
PublishTxnMessage is not supported by non-persistent topic
Error message
PublishTxnMessage is not supported by non-persistent topic
What it means
NonPersistentTopic.publishTxnMessage unconditionally throws UnsupportedOperationException: transactional message publishing requires durable state (pending acks, txn markers) that non-persistent topics cannot maintain, so transactions are unsupported on them.
Source
Thrown at pulsar-broker/src/main/java/org/apache/pulsar/broker/service/nonpersistent/NonPersistentTopic.java:1330
return checkSchemaCompatibleForConsumer(schema)
.exceptionally(ex -> {
Throwable realCause = FutureUtil.unwrapCompletionException(ex);
if (realCause instanceof NotExistSchemaException) {
throw FutureUtil.wrapToCompletionException(
new IncompatibleSchemaException("Failed to add schema to an active topic"
+ " with empty(BYTES) schema: new schema type " + schema.getType()));
}
throw FutureUtil.wrapToCompletionException(realCause);
});
} else {
return addSchema(schema).thenCompose(schemaVersion -> CompletableFuture.completedFuture(null));
}
});
}
@Override
public void publishTxnMessage(TxnID txnID, ByteBuf headersAndPayload, PublishContext publishContext) {
throw new UnsupportedOperationException("PublishTxnMessage is not supported by non-persistent topic");
}
@Override
public CompletableFuture<Void> endTxn(TxnID txnID, int txnAction, long lowWaterMark) {
return FutureUtil.failedFuture(
new Exception("Unsupported operation endTxn in non-persistent topic."));
}
@Override
public CompletableFuture<Void> truncate() {
return FutureUtil.failedFuture(new NotAllowedException("Unsupported truncate"));
}
protected boolean isTerminated() {
return false;
}
View on GitHub (pinned to 820761864e)
Solutions
- Use persistent topics for transactional producers
- Route transactional sends to persistent topics only; check topic type before beginTransaction/send
- Disable transactions for producers bound to non-persistent topics
- Catch UnsupportedOperationException and fall back to non-transactional publish
Example fix
// before
Transaction txn = client.newTransaction().build();
nonPersistentProducer.newMessage(txn).send();
// after
Producer persistentProducer = client.newProducer()
.topic("persistent://public/default/txn-topic").create();
persistentProducer.newMessage(txn).send(); Defensive patterns
Strategy: type-guard
Validate before calling
if (!topicName.getPersistent()) {
// route through a non-transactional producer instead
return producer.newMessage(value).send();
} Type guard
boolean supportsTxnPublish(String topic) {
return topic.startsWith("persistent://");
} Try / catch
try {
producer.newMessage(txn).send();
} catch (UnsupportedOperationException e) {
log.warn("Txn publish unsupported on non-persistent topic; sending non-txn");
} Prevention
- Only use transactions with persistent topics
- Document topic-type constraints in team conventions
- Gate transactional code paths on topic type in messaging abstractions
When it happens
Trigger: Producing a transactional message (transaction.newBuilder().send(...) via producer) to a non-persistent topic; endTxn on a non-persistent topic likewise fails with a failed future.
Common situations: Application configured with transactions enabled but producers targeting non-persistent topics; framework/messaging abstraction picking non-persistent topic while using Pulsar transactions; tests mixing transaction features with non-persistent topics.
Related errors
- Expire message by timestamp is not supported for non-persist
- Expire message by position is not supported for non-persiste
- Failed to add schema to an active topic with empty(BYTES) sc
- Package Management Service is not enabled in the broker.
- This Broker is not configured with transactionCoordinatorEna
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/52c15e3fa10851c6.
Report an issue: GitHub.