apache/pulsar · error · IOException

The path ${path} doesn't look like a valid path for a Bookie

Error message

The path ${path} doesn't look like a valid path for a BookieServiceInfo node

What it means

IOException thrown by BookieServiceInfoSerde.extractBookiedIdFromPath when the metadata-store path has no '/' separator, so no bookie id can be extracted as the trailing path segment. The serde expects paths shaped like <bookie-service-info-root>/<bookieId>.

Source

Thrown at pulsar-metadata/src/main/java/org/apache/pulsar/metadata/bookkeeper/BookieServiceInfoSerde.java:113

     * Extract the BookieId
     * The path should look like /ledgers/available/bookieId
     * or /ledgers/available/readonly/bookieId.
     * But the prefix depends on the configuration.
     * @param path
     * @return the bookieId
     */
    private static String extractBookiedIdFromPath(String path) throws IOException {
        // https://github.com/apache/bookkeeper/blob/
        // 034ef8566ad037937a4d58a28f70631175744f53/bookkeeper-server/
        // src/main/java/org/apache/bookkeeper/discover/ZKRegistrationClient.java#L258
        if (path == null) {
            path = "";
        }
        int last = path.lastIndexOf("/");
        if (last >= 0) {
            return path.substring(last + 1);
        } else {
            throw new IOException("The path " + path + " doesn't look like a valid path for a BookieServiceInfo node");
        }
    }
}

View on GitHub (pinned to 820761864e)

Solutions

  1. Verify the path passed to the serde includes the full bookie-service-info prefix followed by the bookie id
  2. Check the metadata store for stray/malformed nodes under the bookie-service-info root and remove them
  3. Add a pre-check that the path contains '/' before parsing

Example fix

// before
String id = serde.bookieId(pathFromStore); // throws if path has no '/'
// after
if (pathFromStore == null || !pathFromStore.contains("/")) {
    LOG.warn("Skipping malformed bookie service info path: {}", pathFromStore);
    return;
}
String id = serde.bookieId(pathFromStore);
Defensive patterns

Strategy: validation

Validate before calling

if (path == null || !path.contains("/")) {
    throw new IllegalArgumentException("not a BookieServiceInfo path: " + path);
}

Type guard

static boolean isBookieServiceInfoPath(String path) {
    return path != null && path.lastIndexOf('/') >= 0
        && path.lastIndexOf('/') < path.length() - 1;
}

Try / catch

try {
    String id = serde.bookieId(path);
} catch (IOException e) {
    LOG.warn("Skipping malformed bookie info path: {}", path);
}

Prevention

When it happens

Trigger: Calling bookieId() (which delegates to extractBookiedIdFromPath) with a path that is empty, a bare name without '/', or a malformed node path read from the metadata store.

Common situations: Metadata store containing an unexpected node directly at the root of the bookie-service-info directory; a bug or refactor producing relative paths without the root prefix; empty path after a failed substring operation.

Related errors


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