apache/pulsar · error · IOException

Unknown checkpoint type: ${type}

Error message

Unknown checkpoint type: ${type}

What it means

CheckpointV5.fromByteArray switches on the first byte of the encoding (the checkpoint type). If the type byte does not match any known checkpoint type, it throws IOException('Unknown checkpoint type: N'). This indicates the bytes were not produced by a compatible version of this class.

Source

Thrown at pulsar-client-v5/src/main/java/org/apache/pulsar/client/impl/v5/CheckpointV5.java:101

        byte type = buf.get();

        return switch (type) {
            case TYPE_EARLIEST -> EARLIEST;
            case TYPE_LATEST -> LATEST;
            case TYPE_REGULAR -> {
                int numEntries = buf.getInt();
                Map<Long, org.apache.pulsar.client.api.MessageId> positions = new HashMap<>();
                for (int i = 0; i < numEntries; i++) {
                    long segmentId = buf.getLong();
                    int msgIdLen = buf.getInt();
                    byte[] msgIdBytes = new byte[msgIdLen];
                    buf.get(msgIdBytes);
                    positions.put(segmentId,
                            org.apache.pulsar.client.api.MessageId.fromByteArray(msgIdBytes));
                }
                yield new CheckpointV5(positions);
            }
            default -> throw new IOException("Unknown checkpoint type: " + type);
        };
    }

    /**
     * Sentinel checkpoint for earliest/latest positions. Encoded as a single type byte.
     */
    private record SentinelCheckpoint(byte type) implements Checkpoint {
        @Override
        public byte[] toByteArray() {
            ByteBuffer buf = ByteBuffer.allocate(1);
            buf.put(type);
            return buf.array();
        }
    }
}

View on GitHub (pinned to 820761864e)

Solutions

  1. Ensure the client version reading the checkpoint is >= the version that wrote it.
  2. Verify the byte source actually contains CheckpointV5-encoded data (log the first type byte).
  3. Discard the stale checkpoint and rebuild consumer position from a fresh checkpoint.
  4. If you extended checkpoint types in a fork, update the switch in fromByteArray to handle the new type.
Defensive patterns

Strategy: fallback

Validate before calling

if (data != null && data.length > 0) {
    byte type = data[0];
    if (!KNOWN_CHECKPOINT_TYPES.contains(type)) {
        log.warn("Checkpoint type {} not supported by this client, resetting", type);
        return null;
    }
}

Try / catch

try {
    checkpoint = CheckpointV5.fromByteArray(data);
} catch (IOException e) {
    log.warn("Unknown checkpoint type, rebuilding from scratch", e);
    checkpoint = CheckpointV5.earliest();
}

Prevention

When it happens

Trigger: Deserializing a checkpoint written by a newer client version with additional checkpoint types, or a checkpoint blob that is actually some other payload (wrong topic, wrong record, random bytes).

Common situations: Upgrading/downgrading between client versions sharing checkpoint storage; pointing deserialization at a topic or storage key holding non-checkpoint data; endianness or framing mismatch in custom persistence.

Related errors


AI-assisted analysis of apache/pulsar@820761864e (2026-09-06). Data as JSON: /api/errors/9b6e8560fa5999b0. Report an issue: GitHub.