{"record":{"id":"9d22c539b060d5d9","repo":"apache/pulsar","slug":"invalid-magicword-read-0x-x-expected-0x-x-or-0","errorCode":null,"errorMessage":"Invalid MagicWord. read: 0x%x  expected: 0x%x or 0x%x","messagePattern":"Invalid MagicWord\\. read: 0x%x  expected: 0x%x or 0x%x","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"tiered-storage/jcloud/src/main/java/org/apache/bookkeeper/mledger/offload/jcloud/impl/OffloadIndexBlockV2BuilderImpl.java","lineNumber":125,"sourceCode":"        streamingOffset = streamingOffset + lastStreamingBlockSize;\n        lastStreamingBlockSize = blockSize;\n\n        final List<OffloadIndexEntryImpl> list = entryMap.getOrDefault(ledgerId, new LinkedList<>());\n        list.add(OffloadIndexEntryImpl.of(firstEntryId, partId, streamingOffset, dataHeaderLength));\n        entryMap.put(ledgerId, list);\n        return this;\n    }\n\n    @Override\n    public OffloadIndexBlockV2 fromStream(InputStream is) throws IOException {\n        final DataInputStream dataInputStream = new DataInputStream(is);\n        final int magic = dataInputStream.readInt();\n        if (magic == OffloadIndexBlockImpl.getIndexMagicWord()) {\n            return OffloadIndexBlockImpl.get(magic, dataInputStream);\n        } else if (magic == OffloadIndexBlockV2Impl.getIndexMagicWord()) {\n            return OffloadIndexBlockV2Impl.get(magic, dataInputStream);\n        } else {\n            throw new IOException(String.format(\"Invalid MagicWord. read: 0x%x  expected: 0x%x or 0x%x\",\n                    magic, OffloadIndexBlockImpl.getIndexMagicWord(),\n                    OffloadIndexBlockV2Impl.getIndexMagicWord()));\n        }\n    }\n\n    @Override\n    public OffloadIndexBlock build() {\n        checkState(ledgerMetadata != null);\n        checkState(!entries.isEmpty());\n        checkState(dataObjectLength > 0);\n        checkState(dataHeaderLength > 0);\n        return OffloadIndexBlockImpl.get(ledgerMetadata, dataObjectLength, dataHeaderLength, entries);\n    }\n\n    @Override\n    public OffloadIndexBlockV2 buildV2() {\n        checkState(!ledgerMetadataMap.isEmpty());\n        checkState(true);","sourceCodeStart":107,"sourceCodeEnd":143,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/tiered-storage/jcloud/src/main/java/org/apache/bookkeeper/mledger/offload/jcloud/impl/OffloadIndexBlockV2BuilderImpl.java#L107-L143","documentation":"OffloadIndexBlockV2BuilderImpl.fromStream reads the leading magic int and dispatches to either the v1 (OffloadIndexBlockImpl) or v2 (OffloadIndexBlockV2Impl) index parser. If the magic matches neither, the stream is not a recognized offload index format, and an IOException listing the read value and both expected magic words is thrown.","triggerScenarios":"Calling OffloadIndexBlockV2BuilderImpl.fromStream on a stream whose first int is neither INDEX_MAGIC_WORD of v1 nor v2: reading a data block, a future/unknown index format, a corrupted index blob, or a stream positioned mid-object.","commonSituations":"Offloaded by a newer Pulsar with an index format this reader doesn't know; the bucket key points to payload data instead of the index; index blob corrupted in object storage.","solutions":["Confirm the object is an offload index written by a compatible Pulsar version; upgrade the client/broker if the index came from a newer format","Re-offload the ledger to regenerate a readable index if the blob is corrupted","Check the stream is positioned at offset 0 of the index object","Log the read magic value and compare with OffloadIndexBlockImpl/OffloadIndexBlockV2Impl getIndexMagicWord() to identify the actual format"],"exampleFix":"// before: reading index from an arbitrary object\nindex = OffloadIndexBlockBuilderImpl.newBuilder().fromStream(magic, wrongStream);\n// after: resolve the correct index object key first\nString indexKey = DataBlockUtils.parseLedgerId(...); // use the index blob for the ledger\nBlob idxBlob = storage.blob(indexKey);\nindex = OffloadIndexBlockBuilderImpl.newBuilder().fromStream(magic, idxBlob.getPayload().openStream());","handlingStrategy":"try-catch","validationCode":"DataInputStream in = new DataInputStream(new BufferedInputStream(stream));\nin.mark(4);\nint magic = in.readInt();\nin.reset();\nif (magic != OffloadIndexBlockImpl.getIndexMagicWord()\n        && magic != OffloadIndexBlockV2Impl.getIndexMagicWord()) {\n    throw new IOException(\"Unknown index format, magic=0x\" + Integer.toHexString(magic));\n}","typeGuard":null,"tryCatchPattern":"try {\n    OffloadIndexBlock idx = OffloadIndexBlockBuilderImpl.newBuilder().fromStream(magic, stream);\n} catch (IOException e) {\n    if (e.getMessage().startsWith(\"Invalid MagicWord\")) {\n        log.error(\"Index object is not a recognized v1/v2 offload index\");\n    } else { throw e; }\n}","preventionTips":["Upgrade readers before writers when a new index format ships","Ensure the key passed to storage is the index blob for the ledger","Use checksums on the offload bucket to catch corruption","Never parse the data block stream with the index parser"],"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-14T00:17:10.932Z"}