apache/pulsar · warning · ParameterException
Can't expire message by time and by message position at the
Error message
Can't expire message by time and by message position at the same time.
What it means
This error is thrown by the expire-messages CLI command when both --expireTime and --position are supplied. Expiring by time and by message position are mutually exclusive expiration modes, so the command rejects the combination up front via a ParameterException before any admin call is made.
Source
Thrown at pulsar-client-tools/src/main/java/org/apache/pulsar/admin/cli/CmdTopics.java:892
private String subName;
@Option(names = { "-t", "--expireTime" }, description = "Expire messages older than time in seconds "
+ "(or minutes, hours, days, weeks eg: 100m, 3h, 2d, 5w)",
converter = TimeUnitToSecondsConverter.class)
private Long expireTimeInSeconds = -1L;
@Option(names = { "--position",
"-p" }, description = "message position to reset back to (ledgerId:entryId)", required = false)
private String messagePosition;
@Option(names = { "-e", "--exclude-reset-position" },
description = "Exclude the reset position, start consume messages from the next position.")
private boolean excludeResetPosition = false;
@Override
void run() throws PulsarAdminException {
if (expireTimeInSeconds >= 0 && isNotBlank(messagePosition)) {
throw new ParameterException(String.format("Can't expire message by time and "
+ "by message position at the same time."));
}
String topic = validateTopicName(topicName);
if (expireTimeInSeconds >= 0) {
getTopics().expireMessages(topic, subName, expireTimeInSeconds);
} else if (isNotBlank(messagePosition)) {
int partitionIndex = TopicName.get(topic).getPartitionIndex();
MessageId messageId = validateMessageIdString(messagePosition, partitionIndex);
getTopics().expireMessages(topic, subName, messageId, excludeResetPosition);
} else {
throw new ParameterException(
"Either time (--expireTime) or message position (--position) has to be provided"
+ " to expire messages");
}
}
}
@Command(description = "Expire messages that older than given expiry time (in seconds) "View on GitHub (pinned to 820761864e)
Solutions
- Remove either --expireTime or --position so exactly one expiration mode is given
- If you want time-based expiration, drop --position; for position-based, drop --expireTime
- Use -1 (or omit --expireTime) when expiring by position
Example fix
// before pulsar-admin topics expire-messages my-topic -s sub1 --expireTime 3600 --position 10:5 // after pulsar-admin topics expire-messages my-topic -s sub1 --expireTime 3600
Defensive patterns
Strategy: validation
Validate before calling
if (expireTime >= 0 && position != null && !position.isBlank()) {
throw new IllegalArgumentException("Provide only one of --expireTime or --position");
} Type guard
boolean exactlyOne(Object a, Object b) {
boolean hasA = a != null && !(a instanceof Number n && n.longValue() < 0);
boolean hasB = b != null && !b.toString().isBlank();
return hasA ^ hasB;
} Try / catch
try {
admin.topics().expireMessages(topic, sub, expireTime);
} catch (org.apache.pulsar.client.admin.PulsarAdminException e) {
log.error("expire-messages failed", e);
} Prevention
- Pass only one of --expireTime or --position per invocation
- In scripts, guard against both variables being populated
- Use -1 for expireTime when expiring by position
When it happens
Trigger: Running `pulsar-admin topics expire-messages <topic> -s <subscription> --expireTime <secs> --position <position>` — i.e. expireTimeInSeconds >= 0 AND messagePosition is non-blank.
Common situations: Scripted commands accumulating stale flags; users copying an example and adding --position to a time-based expire; automation templates parameterized with both values set.
Related errors
- If you set --clear then you should not pass any properties
- --destinationBroker cannot be set when --bundle is not speci
- Must pass one of the params: --bundle / --bundle-type
- --bundle and --bundle-type are mutually exclusive
- Must pass one of the params: --bundle
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/d5c906c0a5ea8f55.
Report an issue: GitHub.