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

  1. Remove either --expireTime or --position so exactly one expiration mode is given
  2. If you want time-based expiration, drop --position; for position-based, drop --expireTime
  3. 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

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


AI-assisted analysis of apache/pulsar@820761864e (2026-09-06). Data as JSON: /api/errors/d5c906c0a5ea8f55. Report an issue: GitHub.