{"record":{"id":"9f47c5476d51d61e","repo":"apache/pulsar","slug":"it-is-not-a-valid-hashed-path-name-ledgerpath","errorCode":null,"errorMessage":"it is not a valid hashed path name : ${ledgerPath}","messagePattern":"it is not a valid hashed path name : (.+?)","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"pulsar-metadata/src/main/java/org/apache/pulsar/metadata/bookkeeper/PulsarLedgerManager.java","lineNumber":377,"sourceCode":"\n    @Override\n    public void close() throws IOException {\n        scheduler.shutdownNow();\n        try {\n            scheduler.awaitTermination(10, TimeUnit.SECONDS);\n        } catch (InterruptedException ie) {\n            Thread.currentThread().interrupt();\n            throw new IOException(ie);\n        }\n    }\n\n    public String getLedgerPath(long ledgerId) {\n        return this.ledgerRootPath + StringUtils.getHybridHierarchicalLedgerPath(ledgerId);\n    }\n\n    private long getLedgerId(String ledgerPath) throws IOException {\n        if (!ledgerPath.startsWith(ledgerRootPath)) {\n            throw new IOException(\"it is not a valid hashed path name : \" + ledgerPath);\n        }\n        String hierarchicalPath = ledgerPath.substring(ledgerRootPath.length() + 1);\n        return StringUtils.stringToLongHierarchicalLedgerId(hierarchicalPath);\n    }\n\n\n    /**\n     * ReadLedgerMetadataTask class.\n     */\n    private class ReadLedgerMetadataTask implements Runnable {\n\n        final long ledgerId;\n\n        ReadLedgerMetadataTask(long ledgerId) {\n            this.ledgerId = ledgerId;\n        }\n\n        @Override","sourceCodeStart":359,"sourceCodeEnd":395,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-metadata/src/main/java/org/apache/pulsar/metadata/bookkeeper/PulsarLedgerManager.java#L359-L395","documentation":"PulsarLedgerManager.getLedgerId converts a metadata-store znode path back into a BookKeeper ledger id. If the given path does not start with the configured ledgerRootPath, it cannot be a ledger znode managed by this ledger manager, so an IOException is thrown naming the offending path.","triggerScenarios":"Calling getLedgerId (via deserialize or handleDataNotification) with a path from outside the ledgers root, e.g. a path whose prefix differs from the configured ledgerRootPath (typo, trailing slash mismatch, or a notification for a node not under the ledgers hierarchy).","commonSituations":"Misconfigured metadataServiceUri / ledgersRootPath that changed after ledgers were created; metadata-watch notifications firing for unrelated znodes; manually moving or copying ledgers data under a different root; running multiple BookKeeper clusters against one metadata store.","solutions":["Verify the ledgerRootPath in the broker/bookkeeper configuration matches the actual path where ledger znodes live in the metadata store.","Check the path in the error message: if it legitimately lives elsewhere, do not pass it to this ledger manager's getLedgerId/deserialize.","If paths were migrated, rewrite or re-create the ledger hierarchy under the configured root (e.g. with BookKeeper shell) instead of pointing config at the old data.","Inspect who produced the path (handleDataNotification watch vs deserialize of stored data) and filter out nodes not under the ledgers root before parsing."],"exampleFix":"// before\nlong ledgerId = ledgerManager.getLedgerId(notificationPath);\n// after\nif (notificationPath.startsWith(conf.getLedgerRootPath())) {\n    long ledgerId = ledgerManager.getLedgerId(notificationPath);\n} else {\n    log.warn(\"Ignoring notification for foreign path {}\", notificationPath);\n}","handlingStrategy":"validation","validationCode":"if (path != null && path.startsWith(ledgerRootPath + \"/\")) {\n    long ledgerId = ledgerManager.getLedgerId(path);\n}","typeGuard":null,"tryCatchPattern":"try {\n    long ledgerId = ledgerManager.getLedgerId(path);\n} catch (IOException e) {\n    log.warn(\"Not a ledger path: {}\", path); // skip foreign notifications\n}","preventionTips":["Keep ledgerRootPath configuration identical across all brokers and bookies.","Filter metadata-watch notifications to paths under the configured ledgers root before parsing.","After any ledgers root migration, re-verify stored paths match the new config."],"tags":["bookkeeper","metadata-store","ledger-path","configuration"],"backgroundTag":"invalid-ledger-path","analyzedSha":"820761864ed8e2a7d2e52dd9763ad2ae117c1395","analyzedAt":"2026-09-06T00:14:20.138Z","contentChangedAt":"2026-09-06T00:14:20.138Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}