apache/pulsar · error · IllegalArgumentException
Invalid managedLedger name: ${mlName}
Error message
Invalid managedLedger name: ${mlName} What it means
fromPersistenceNamingEncoding converts a legacy managed-ledger storage path (the on-disk name used by BookKeeper/Pulsar metadata, with encoded segments) back into a topic URL. If the managedLedger name does not have the expected segment structure (it is not a recognized legacy or current encoding), the method throws this IllegalArgumentException because the name cannot be decoded.
Source
Thrown at pulsar-common/src/main/java/org/apache/pulsar/common/naming/TopicName.java:490
return String.format("%s://%s/%s/%s", domain, tenant, namespacePortion, localName);
} else if (parts.size() == 5) {
if ("segment".equals(parts.get(2))) {
// Segment topic ML name: tenant/namespace/segment/topic/descriptor
tenant = parts.get(0);
namespacePortion = parts.get(1);
localName = Codec.decode(parts.get(3));
return String.format("segment://%s/%s/%s/%s", tenant, namespacePortion, localName, parts.get(4));
}
// Legacy V1 managed ledger name: tenant/cluster/namespace/domain/topic
// Convert to V2 format, dropping the cluster component
tenant = parts.get(0);
// parts.get(1) is the cluster, which we drop
namespacePortion = parts.get(2);
domain = parts.get(3);
localName = Codec.decode(parts.get(4));
return String.format("%s://%s/%s/%s", domain, tenant, namespacePortion, localName);
} else {
throw new IllegalArgumentException("Invalid managedLedger name: " + mlName);
}
}
/**
* Get a string suitable for completeTopicName lookup.
*
* <p>Example:
*
* <p>persistent://tenant/namespace/completeTopicName ->
* persistent/tenant/namespace/completeTopicName
*
* @return
*/
public String getLookupName() {
return String.format("%s/%s/%s/%s", domain, tenant, namespacePortion, getEncodedLocalName());
}
public String getSchemaName() {View on GitHub (pinned to 820761864e)
Solutions
- Pass the full managed-ledger name exactly as stored (all segments), e.g. 'tenant/cluster/namespace/domain/persistent/localName' legacy form or the current 'tenant/namespace/persistent/localName'
- Verify you are not truncating the path when extracting from metadata storage
- If converting a topic name to ledger form, use TopicName.getPersistenceNamingEncoding() first and round-trip it
Example fix
// before
TopicName.fromPersistenceNamingEncoding("persistent/my-topic");
// after
TopicName.fromPersistenceNamingEncoding("my-tenant/my-cluster/my-ns/persistent/my-topic"); Defensive patterns
Strategy: validation
Validate before calling
public static boolean looksLikeManagedLedgerName(String mlName) {
if (mlName == null) return false;
String[] parts = mlName.split("/");
return parts.length == 5 // legacy: tenant/cluster/namespace/domain/localName
|| (parts.length == 4 && (parts[2].equals("persistent") || parts[2].equals("non-persistent")));
} Type guard
public static boolean isDecodableLedgerName(String s) { return s != null && s.split("/").length >= 4; } Try / catch
try {
String topicUrl = TopicName.fromPersistenceNamingEncoding(mlName);
} catch (IllegalArgumentException e) {
log.error("Cannot decode managed ledger name '{}': {}", mlName, e.getMessage());
} Prevention
- Round-trip through getPersistenceNamingEncoding() instead of hand-building ledger names
- Do not truncate paths read from ZooKeeper/BookKeeper metadata
- Account for the legacy 5-part (with cluster) vs modern 4-part scheme when migrating data
When it happens
Trigger: Calling TopicName.fromPersistenceNamingEncoding(mlName) with a string that does not match the expected managed-ledger naming scheme — wrong number of slash-separated parts (the code expects 5 parts for the legacy format, or the modern 3-part tenant/namespace/local form), or a corrupted/shortened path read from metadata storage.
Common situations: Reading entries directly from ZooKeeper/BookKeeper metadata and passing the raw ledger path; hand-building ledger names; migrating data between Pulsar versions where the naming scheme differs; passing an encoded name with missing segments.
Related errors
- Invalid value %s for the position. Allowed values are [lates
- Invalid topic name ${topic}
- Timeout during managed ledger close
- Timeout during managed ledger delete operation
- Timeout during managed ledger offload operation
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/877c5f983286247e.
Report an issue: GitHub.