{"record":{"id":"eb7b63eea6799f3c","repo":"apache/pulsar","slug":"header-was-too-small-eb7b63","errorCode":null,"errorMessage":"Header was too small","messagePattern":"Header was too small","errorType":"exception","errorClass":"EOFException","httpStatus":null,"severity":"error","filePath":"tiered-storage/jcloud/src/main/java/org/apache/bookkeeper/mledger/offload/jcloud/impl/StreamingDataBlockHeaderImpl.java","lineNumber":108,"sourceCode":"    }\n\n    // Construct DataBlockHeader from InputStream, which contains `HEADER_MAX_SIZE` bytes readable.\n    public static StreamingDataBlockHeaderImpl fromStream(InputStream stream) throws IOException {\n        CountingInputStream countingStream = new CountingInputStream(stream);\n        DataInputStream dis = new DataInputStream(countingStream);\n        int magic = dis.readInt();\n        if (magic != MAGIC_WORD) {\n            throw new IOException(\"Data block header magic word not match. read: \" + magic\n                    + \" expected: \" + MAGIC_WORD);\n        }\n\n        long headerLen = dis.readLong();\n        long blockLen = dis.readLong();\n        long firstEntryId = dis.readLong();\n        long ledgerId = dis.readLong();\n        long toSkip = headerLen - countingStream.getCount();\n        if (dis.skip(toSkip) != toSkip) {\n            throw new EOFException(\"Header was too small\");\n        }\n\n        return new StreamingDataBlockHeaderImpl(headerLen, blockLen, ledgerId, firstEntryId);\n    }\n\n    /**\n     * Get the content of the data block header as InputStream.\n     * Read out in format:\n     *   [ magic_word -- int ][ block_len -- int ][ first_entry_id  -- long] [padding zeros]\n     */\n    @Override\n    public InputStream toStream() {\n        ByteBuf out = PulsarByteBufAllocator.DEFAULT.buffer(HEADER_MAX_SIZE, HEADER_MAX_SIZE);\n        out.writeInt(MAGIC_WORD)\n                .writeLong(headerLength)\n                .writeLong(blockLength)\n                .writeLong(firstEntryId)\n                .writeLong(ledgerId)","sourceCodeStart":90,"sourceCodeEnd":126,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/tiered-storage/jcloud/src/main/java/org/apache/bookkeeper/mledger/offload/jcloud/impl/StreamingDataBlockHeaderImpl.java#L90-L126","documentation":"Offload deserialization guard in StreamingDataBlockHeaderImpl.fromStream: after the magic word check passes, the header length read from the stream is smaller than the minimum block-header size, so the block header cannot be fully constructed — indicates a corrupt or truncated data block in tiered storage.","triggerScenarios":"Thrown at tiered-storage/jcloud/src/main/java/org/apache/bookkeeper/mledger/offload/jcloud/impl/StreamingDataBlockHeaderImpl.java:108 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Check for truncated object storage files","Verify the read offset and object size in the offload driver configuration"],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"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"}