{"record":{"id":"65af354944d33f8e","repo":"apache/pulsar","slug":"invalid-checkpoint-data-empty","errorCode":null,"errorMessage":"Invalid checkpoint data: empty","messagePattern":"Invalid checkpoint data: empty","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"pulsar-client-v5/src/main/java/org/apache/pulsar/client/impl/v5/CheckpointV5.java","lineNumber":79,"sourceCode":"            byte[] idBytes = entry.getValue().toByteArray();\n            serializedIds.put(entry.getKey(), idBytes);\n            totalSize += 8 + 4 + idBytes.length;\n        }\n\n        ByteBuffer buf = ByteBuffer.allocate(totalSize);\n        buf.put(TYPE_REGULAR);\n        buf.putInt(segmentPositions.size());\n        for (var entry : serializedIds.entrySet()) {\n            buf.putLong(entry.getKey());\n            buf.putInt(entry.getValue().length);\n            buf.put(entry.getValue());\n        }\n        return buf.array();\n    }\n\n    static Checkpoint fromByteArray(byte[] data) throws IOException {\n        if (data == null || data.length < 1) {\n            throw new IOException(\"Invalid checkpoint data: empty\");\n        }\n\n        ByteBuffer buf = ByteBuffer.wrap(data);\n        byte type = buf.get();\n\n        return switch (type) {\n            case TYPE_EARLIEST -> EARLIEST;\n            case TYPE_LATEST -> LATEST;\n            case TYPE_REGULAR -> {\n                int numEntries = buf.getInt();\n                Map<Long, org.apache.pulsar.client.api.MessageId> positions = new HashMap<>();\n                for (int i = 0; i < numEntries; i++) {\n                    long segmentId = buf.getLong();\n                    int msgIdLen = buf.getInt();\n                    byte[] msgIdBytes = new byte[msgIdLen];\n                    buf.get(msgIdBytes);\n                    positions.put(segmentId,\n                            org.apache.pulsar.client.api.MessageId.fromByteArray(msgIdBytes));","sourceCodeStart":61,"sourceCodeEnd":97,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-client-v5/src/main/java/org/apache/pulsar/client/impl/v5/CheckpointV5.java#L61-L97","documentation":"CheckpointV5.fromByteArray deserializes a checkpoint from its byte encoding, which must start with a type byte. If the byte array is null or has zero length, there is no type byte to read, so it throws IOException('Invalid checkpoint data: empty'). This guards against corrupt or truncated stored checkpoints.","triggerScenarios":"Calling CheckpointV5.fromByteArray(null) or fromByteArray(new byte[0]) — typically from a corrupted or empty checkpoint record read back from storage.","commonSituations":"Restoring consumer state after a crash where the checkpoint file/record was truncated or never written; migration tooling feeding legacy/empty blobs into the v5 deserializer.","solutions":["Check the checkpoint byte array is non-null and non-empty before calling fromByteArray.","Regenerate the checkpoint by re-consuming/re-acknowledging to write a fresh checkpoint.","Verify the storage backend did not truncate the record (check write flush, record size metadata)."],"exampleFix":"// before\nCheckpoint cp = CheckpointV5.fromByteArray(raw);\n// after\nif (raw == null || raw.length < 1) {\n    throw new IOException(\"No checkpoint stored, starting fresh\");\n}\nCheckpoint cp = CheckpointV5.fromByteArray(raw);","handlingStrategy":"validation","validationCode":"if (data == null || data.length < 1) {\n    // no checkpoint stored — start fresh\n    return null;\n}","typeGuard":null,"tryCatchPattern":"try {\n    checkpoint = CheckpointV5.fromByteArray(data);\n} catch (IOException e) {\n    log.warn(\"Unreadable checkpoint, starting fresh\", e);\n    checkpoint = null;\n}","preventionTips":["Persist checkpoints atomically (write temp + rename) so readers never see empty records.","Check record length before deserializing.","Distinguish 'no checkpoint' from 'corrupt checkpoint' in storage metadata."],"tags":["deserialization","checkpoint","corrupt-data"],"backgroundTag":"invalid-checkpoint-data","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"}