apache/pulsar · error · PulsarAdminException

Invalid message id (must be in format: ledgerId:entryId)…

Error message

Invalid message id (must be in format: ledgerId:entryId) value ${resetMessageIdStr}

What it means

CliCommand.validateMessageIdString parses a message id string that must be exactly 'ledgerId:entryId' (two colon-separated longs), optionally attaching a partition index. Guava Preconditions.checkArgument and Long.parseLong failures are caught and rethrown as PulsarAdminException with the offending value echoed, so any malformed input lands here.

Solutions

  1. Format the argument as exactly two colon-separated longs: ledgerId:entryId (e.g. 12:34)
  2. Strip extra components (partition index, batch index) from the copied message id before passing it
  3. Verify both parts are valid non-empty decimal longs with no whitespace
  4. If you have a MessageId object, serialize it yourself into 'ledgerId:entryId' rather than trusting toString() output

Example fix

// before
--message-id 12:34:5
// after
--message-id 12:34
Defensive patterns

Strategy: validation

Validate before calling

// Validate the message id string before passing it to the CLI
String mid = resetMessageIdStr.trim();
if (!mid.matches("\\d+:\\d+")) {
    throw new IllegalArgumentException("message id must be ledgerId:entryId, got: " + resetMessageIdStr);
}

Try / catch

try {
    admin.topics().resetCursor(topic, subscription, messageId);
} catch (PulsarAdminException e) {
    if (e.getMessage() != null && e.getMessage().contains("Invalid message id")) {
        log.error("Fix format to ledgerId:entryId; input was: {}", resetMessageIdStr);
    }
    throw e;
}

Prevention

When it happens

Trigger: Passing a reset-cursor or similar admin command a message id that is not ledgerId:entryId — e.g. '123:45:67', 'abc:def', '123-45', an empty string, or a MessageId.toString() variant with extra components like 'ledgerId:entryId:partitionIndex'.

Common situations: Copy-pasting a message id from logs that includes extra fields; using a broker's verbose message id format with batch index or partition suffix; typos in manual cursor-reset operations; using 'latest'/'earliest' special values where the command expects numeric ids.

Related errors


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

Appendix: source

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

    static String validateNonPersistentTopic(String topic) {
        TopicName topicName = TopicName.get(topic);
        if (topicName.getDomain() != TopicDomain.non_persistent) {
            throw new IllegalArgumentException("Need to provide a non-persistent topic name");
        }
        return topicName.toString();
    }

    static MessageId validateMessageIdString(String resetMessageIdStr) throws PulsarAdminException {
        return validateMessageIdString(resetMessageIdStr, -1);
    }

    static MessageId validateMessageIdString(String resetMessageIdStr, int partitionIndex) throws PulsarAdminException {
        String[] messageId = resetMessageIdStr.split(":");
        try {
            com.google.common.base.Preconditions.checkArgument(messageId.length == 2);
            return new MessageIdImpl(Long.parseLong(messageId[0]), Long.parseLong(messageId[1]), partitionIndex);
        } catch (Exception e) {
            throw new PulsarAdminException(
                    "Invalid message id (must be in format: ledgerId:entryId) value " + resetMessageIdStr);
        }
    }

    Set<AuthAction> getAuthActions(List<String> actions) {
        Set<AuthAction> res = new TreeSet<>();
        AuthAction authAction;
        for (String action : actions) {
            try {
                authAction = AuthAction.valueOf(action);
            } catch (IllegalArgumentException exception) {
                throw new ParameterException(String.format("Illegal auth action '%s'. Possible values: %s",
                        action, Arrays.toString(AuthAction.values())));
            }
            res.add(authAction);
        }

        return res;

View on GitHub (pinned to 820761864e)