{"record":{"id":"78cecddc2e5eb542","repo":"apache/pulsar","slug":"invalid-magicword-read-0x-x-expected-0x-x-78cecd","errorCode":null,"errorMessage":"Invalid MagicWord. read: 0x%x  expected: 0x%x","messagePattern":"Invalid MagicWord\\. read: 0x%x  expected: 0x%x","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"tiered-storage/jcloud/src/main/java/org/apache/bookkeeper/mledger/offload/jcloud/impl/OffloadIndexBlockV2Impl.java","lineNumber":96,"sourceCode":"                    .getOrDefault(ledgerId, new TreeMap<>());\n            list.forEach(indexEntry -> {\n                inLedger.put(indexEntry.getEntryId(), indexEntry);\n            });\n            block.indexEntries.put(ledgerId, inLedger);\n        });\n\n        block.segmentMetadata = metadata;\n        block.dataObjectLength = dataObjectLength;\n        block.dataHeaderLength = dataHeaderLength;\n        return block;\n    }\n\n    public static OffloadIndexBlockV2Impl get(int magic, DataInputStream stream) throws IOException {\n        OffloadIndexBlockV2Impl block = RECYCLER.get();\n        block.indexEntries = Maps.newTreeMap();\n        block.segmentMetadata = Maps.newTreeMap();\n        if (magic != INDEX_MAGIC_WORD) {\n            throw new IOException(String.format(\"Invalid MagicWord. read: 0x%x  expected: 0x%x\",\n                    magic, INDEX_MAGIC_WORD));\n        }\n        block.fromStream(stream);\n        return block;\n    }\n\n    public void recycle() {\n        dataObjectLength = -1;\n        dataHeaderLength = -1;\n        segmentMetadata = null;\n        indexEntries.clear();\n        indexEntries = null;\n        if (recyclerHandle != null) {\n            recyclerHandle.recycle(this);\n        }\n    }\n\n    @Override","sourceCodeStart":78,"sourceCodeEnd":114,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/tiered-storage/jcloud/src/main/java/org/apache/bookkeeper/mledger/offload/jcloud/impl/OffloadIndexBlockV2Impl.java#L78-L114","documentation":"OffloadIndexBlockV2Impl.get deserializes the v2 offload index: the supplied magic int must equal the v2 INDEX_MAGIC_WORD. Otherwise the stream is not a v2 index block (wrong format version or corruption), and an IOException showing read vs expected magic is thrown before parsing entries.","triggerScenarios":"Calling OffloadIndexBlockV2Impl.get on a stream whose leading int is not the v2 magic — most commonly a v1 index passed directly to the v2 parser, a data block, or a corrupted/truncated index object.","commonSituations":"Hard-coding the v2 parser for ledgers offloaded by older brokers (v1 format); objects copied/corrupted in storage; reading from the wrong stream offset.","solutions":["Use OffloadIndexBlockV2BuilderImpl.fromStream to auto-detect v1 vs v2 magic instead of calling the v2 parser directly","Confirm the offload format version of the object and use the matching parser","Re-offload the ledger if the index blob is corrupted","Verify the stream starts at the index object's first byte"],"exampleFix":"// before: force v2 parsing\nOffloadIndexBlockV2Impl idx = OffloadIndexBlockV2Impl.get(magic, stream);\n// after: format-agnostic parse\nOffloadIndexBlock idx = OffloadIndexBlockBuilderImpl.newBuilder()\n    .fromStream(magic, stream); // dispatches on magic word","handlingStrategy":"try-catch","validationCode":"int magic = stream.readInt(); // after marking/resetting\nif (magic != OffloadIndexBlockV2Impl.getIndexMagicWord()) {\n    throw new IOException(\"Not a v2 offload index, magic=0x\" + Integer.toHexString(magic));\n}","typeGuard":null,"tryCatchPattern":"try {\n    OffloadIndexBlockV2Impl idx = OffloadIndexBlockV2Impl.get(magic, stream);\n} catch (IOException e) {\n    if (e.getMessage().startsWith(\"Invalid MagicWord\")) {\n        // likely a v1 index: fall back to OffloadIndexBlockImpl.get\n    } else { throw e; }\n}","preventionTips":["Detect format via magic word (use the V2 builder's fromStream) instead of hardcoding v2","Match parser version to the broker version that offloaded the data","Validate object integrity before parsing","Read from byte 0 of the index object"],"tags":["io","corruption","index-block","format-version"],"backgroundTag":"magic-word-mismatch","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"}