apache/pulsar · warning · PulsarAdminException

Either Timestamp (--time) or messageId (--messageId) has to

Error message

Either Timestamp (--time) or messageId (--messageId) has to be provided to reset cursor

What it means

The reset-cursor command needs a target: either an absolute timestamp (--time), a relative time (--currentTime/-time offset), or a messageId (--messageId). If none is provided, it throws PulsarAdminException since the cursor cannot be reset without a reset point.

Source

Thrown at pulsar-client-tools/src/main/java/org/apache/pulsar/admin/cli/CmdTopics.java:1061

                MessageId messageId;
                if ("earliest".equals(resetMessageIdStr)) {
                    messageId = MessageId.earliest;
                } else if ("latest".equals(resetMessageIdStr)) {
                    messageId = MessageId.latest;
                } else {
                    messageId = validateMessageIdString(resetMessageIdStr);
                }
                if (excludeResetPosition) {
                    getTopics().resetCursor(persistentTopic, subName, messageId, true);
                } else {
                    getTopics().resetCursor(persistentTopic, subName, messageId);
                }
            } else if (Objects.nonNull(resetTimeInMillis)) {
                // now - go back time
                long timestamp = System.currentTimeMillis() - resetTimeInMillis;
                getTopics().resetCursor(persistentTopic, subName, timestamp);
            } else {
                throw new PulsarAdminException(
                        "Either Timestamp (--time) or messageId (--messageId) has to be provided to reset cursor");
            }
        }
    }

    @Command(description = "Terminate a topic and don't allow any more messages to be published")
    private class Terminate extends CliCommand {
        @Parameters(description = "persistent://tenant/namespace/topic", arity = "1")
        private String topicName;

        @Override
        void run() throws PulsarAdminException {
            String persistentTopic = validatePersistentTopic(topicName);

            try {
                MessageId lastMessageId = getTopics().terminateTopicAsync(persistentTopic).get();
                System.out.println("Topic successfully terminated at " + lastMessageId);
            } catch (InterruptedException | ExecutionException e) {

View on GitHub (pinned to 820761864e)

Solutions

  1. Add --messageId <ledgerId:entryId> to reset to a specific position
  2. Or add --time <timestamp> (epoch millis) for an absolute reset point
  3. Or supply a relative time so resetTimeInMillis is non-null (e.g. reset N ms back)

Example fix

// before
pulsar-admin topics reset-cursor my-topic -s sub1
// after
pulsar-admin topics reset-cursor my-topic -s sub1 --messageId 1024:0
Defensive patterns

Strategy: validation

Validate before calling

if (time == null && messageId == null && relativeTimeMs == null) {
    throw new IllegalArgumentException("Provide --time, --messageId, or a relative time to reset cursor");
}

Try / catch

try {
    admin.topics().resetCursor(topic, sub, messageIdOrTimestamp);
} catch (org.apache.pulsar.client.admin.PulsarAdminException e) {
    log.error("reset-cursor requires --time or --messageId", e);
}

Prevention

When it happens

Trigger: Running `pulsar-admin topics reset-cursor <topic> -s <sub>` with no --time, no relative time, and no --messageId.

Common situations: Scripts where the timestamp variable is empty; users expecting a default of 'now'; mixing up reset-cursor options in automation.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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