apache/pulsar · error · IllegalArgumentException
Invalid value %s for the position. Allowed values are [lates
Error message
Invalid value %s for the position. Allowed values are [latest, earliest]
What it means
ResetCursorData's String constructor only accepts the exact literals "latest" and "earliest" as a position; any other string cannot be mapped to a message position and triggers this IllegalArgumentException. Use the MessageId constructor for arbitrary positions.
Source
Thrown at pulsar-client/src/main/java/org/apache/pulsar/client/impl/ResetCursorData.java:65
}
public ResetCursorData(long ledgerId, long entryId, boolean isExcluded, Map<String, String> properties) {
this.ledgerId = ledgerId;
this.entryId = entryId;
this.isExcluded = isExcluded;
this.properties = properties;
}
// Private constructor used only for json deserialization
private ResetCursorData(String position) {
if ("latest".equals(position)) {
this.ledgerId = Long.MAX_VALUE;
this.entryId = Long.MAX_VALUE;
} else if ("earliest".equals(position)) {
this.ledgerId = -1;
this.entryId = -1;
} else {
throw new IllegalArgumentException(
String.format("Invalid value %s for the position. Allowed values are [latest, earliest]",
position));
}
}
public ResetCursorData(MessageId messageId) {
MessageIdAdv messageIdAdv = (MessageIdAdv) messageId;
this.ledgerId = messageIdAdv.getLedgerId();
this.entryId = messageIdAdv.getEntryId();
this.batchIndex = messageIdAdv.getBatchIndex();
this.partitionIndex = messageIdAdv.getPartitionIndex();
if (messageId instanceof TopicMessageId) {
throw new IllegalArgumentException("Not supported operation on partitioned-topic");
}
}
}
View on GitHub (pinned to 820761864e)
Solutions
- Normalize input with position.trim().toLowerCase() before constructing ResetCursorData
- Map alternative synonyms (beginning->earliest, end->latest) before calling the constructor
- For arbitrary positions use new ResetCursorData(MessageId) instead of the string form
Example fix
// before
new ResetCursorData("LATEST"); // throws
// after
String p = input.trim().toLowerCase(Locale.ROOT);
new ResetCursorData(p); // "latest" or "earliest" Defensive patterns
Strategy: validation
Validate before calling
if (!"latest".equals(position) && !"earliest".equals(position)) {
throw new IllegalArgumentException("position must be 'latest' or 'earliest'");
} Type guard
boolean isKnownPosition(String p) {
return "latest".equals(p) || "earliest".equals(p);
} Try / catch
try {
resetCursorData = new ResetCursorData(position);
} catch (IllegalArgumentException e) {
log.warn("Invalid reset position '{}', defaulting to latest", position);
resetCursorData = new ResetCursorData("latest");
} Prevention
- Normalize case/whitespace on user-supplied position strings before constructing
- Prefer the ResetCursorData(MessageId) constructor for programmatic positions
- Document the accepted literals [latest, earliest] where the position string is captured
When it happens
Trigger: Building ResetCursorData from user/CLI/API input where the position string is anything other than exactly "latest" or "earliest" (case differences like "Latest"/"LATEST", whitespace, or synonyms like "beginning"/"end").
Common situations: REST/admin tooling passing a user-supplied reset-position string through unvalidated; config files with mixed-case values; older code using "beginning"/"end" conventions instead of "earliest"/"latest".
Related errors
- The shared resource doesn't support thread pool configurati
- No resources have been configured while using shareConfigure
- Ranges must be [0, 65535] but provided range is
- Key hash ranges with overlap between and
- Error creating client for HealthChecker
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/8fabd623f0296976.
Report an issue: GitHub.