apache/pulsar · error · NumberFormatException
Couldn't find ledgerid in path
Error message
Couldn't find ledgerid in path
What it means
getLedgerId extracts the numeric ledger id from an underreplication znode path using ID_EXTRACTION_PATTERN. If the regex finds no match (the path doesn't have the expected .../ledgers/region/xx/xx/ledgerId shape), it throws NumberFormatException with this message.
Source
Thrown at pulsar-metadata/src/main/java/org/apache/pulsar/metadata/bookkeeper/PulsarLedgerUnderreplicationManager.java:221
|| layout.getVersion() != LAYOUT_VERSION) {
throw new ReplicationException.CompatibilityException(
"Incompatible layout found (" + LAYOUT + ":" + LAYOUT_VERSION + ")");
}
} catch (RuntimeException pe) {
throw new ReplicationException.CompatibilityException(
"Invalid data found", pe);
}
break;
}
}
}
private long getLedgerId(String path) throws NumberFormatException {
Matcher m = ID_EXTRACTION_PATTERN.matcher(path);
if (m.find()) {
return Long.parseLong(m.group(1));
} else {
throw new NumberFormatException("Couldn't find ledgerid in path");
}
}
private static String getParentPath(String base, long ledgerId) {
String subdir1 = String.format("%04x", ledgerId >> 48 & 0xffff);
String subdir2 = String.format("%04x", ledgerId >> 32 & 0xffff);
String subdir3 = String.format("%04x", ledgerId >> 16 & 0xffff);
String subdir4 = String.format("%04x", ledgerId & 0xffff);
return String.format("%s/%s/%s/%s/%s",
base, subdir1, subdir2, subdir3, subdir4);
}
public static String getUrLedgerPath(String base, long ledgerId) {
return String.format("%s/urL%010d", getParentPath(base, ledgerId), ledgerId);
}
public static String getUrLedgerLockPath(String base, long ledgerId) {View on GitHub (pinned to 820761864e)
Solutions
- Filter out special znodes (AbstractZkLedgerManager.isSpecialZnode or equivalent checks) before parsing paths.
- Verify the path matches the expected hierarchical pattern <base>/region/dd/dd/<ledgerId> produced by getParentPath.
- Fix the caller to only pass paths obtained from getLedgerList/underreplication hierarchy rather than arbitrary znode paths.
- If building paths yourself, use getParentPath-style formatting (String.format("%04x", ...)) rather than string concatenation.
Example fix
// before
long id = urManager.ledgerId(anyChildPath);
// after
if (AbstractZkLedgerManager.isSpecialZnode(anyChildPath)) {
return; // skip layout/lock nodes
}
long id = urManager.ledgerId(anyChildPath); Defensive patterns
Strategy: type-guard
Validate before calling
private static final Pattern LEDGER_PATH = Pattern.compile(".*/(\\d+)$");
boolean isLedgerPath(String p) { return LEDGER_PATH.matcher(p).matches(); } Type guard
boolean isParseableLedgerPath(String path) {
return path != null && ID_EXTRACTION_PATTERN.matcher(path).find();
} Try / catch
try {
long id = urManager.ledgerId(path);
} catch (NumberFormatException e) {
log.debug("Skipping non-ledger znode path {}", path);
} Prevention
- Skip special znodes before parsing paths from the underreplication hierarchy.
- Only feed paths produced by the underreplication manager's own path builders into ledgerId().
- Use isSpecialZnode-style checks when iterating children of the underreplication root.
When it happens
Trigger: Calling ledgerId/getLedgerId with a path that doesn't conform to the underreplication hierarchy — special znodes (locks, layout, management nodes) or arbitrary paths passed into the underreplication manager's path-parsing APIs.
Common situations: Iterating all children of the underreplication root without filtering special znodes; custom tooling constructing paths with wrong format; path changes between Pulsar versions breaking hand-written parsers.
Related errors
- The path ${path} doesn't look like a valid path for a Bookie
- it is not a valid hashed path name : ${pathName}
- Incompatible layout found (LAYOUT:1)
- Invalid data found
- Cursor %s mark-delete position %s is ahead of the last posit
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/f1565647b92fe401.
Report an issue: GitHub.