apache/pulsar · error · java.io.IOException

Invalid MessageIdV5 data: bad inner id length

Error message

Invalid MessageIdV5 data: bad inner id length

What it means

readSegmentVector parses section 3: a count, then per entry an 8-byte segment id, a 4-byte inner-id length, and the id bytes. If an inner id length is negative or exceeds remaining bytes, the buffer is corrupt/misaligned, so it throws IOException('Invalid MessageIdV5 data: bad inner id length'). Called from fromByteArray and inner.

Source

Thrown at pulsar-client-v5/src/main/java/org/apache/pulsar/client/impl/v5/MessageIdV5.java:326

                    buf.get(topicBytes);
                    String topic = new String(topicBytes, StandardCharsets.UTF_8);
                    Map<Long, MessageId> inner = readSegmentVector(buf);
                    multiTopic.put(topic, inner);
                }
            }
        }

        return new MessageIdV5(v4Id, segmentId, positions, parentTopic, multiTopic);
    }

    private static Map<Long, MessageId> readSegmentVector(ByteBuffer buf) throws IOException {
        int count = buf.getInt();
        Map<Long, MessageId> out = new HashMap<>(count);
        for (int i = 0; i < count; i++) {
            long segId = buf.getLong();
            int idLen = buf.getInt();
            if (idLen < 0 || idLen > buf.remaining()) {
                throw new IOException("Invalid MessageIdV5 data: bad inner id length");
            }
            byte[] idBytes = new byte[idLen];
            buf.get(idBytes);
            out.put(segId, MessageId.fromByteArray(idBytes));
        }
        return out;
    }

    @Override
    public int compareTo(org.apache.pulsar.client.api.v5.MessageId other) {
        if (!(other instanceof MessageIdV5 o)) {
            throw new IllegalArgumentException("Cannot compare with " + other.getClass());
        }
        int cmp = Long.compare(this.segmentId, o.segmentId);
        if (cmp != 0) {
            return cmp;
        }
        return this.v4MessageId.compareTo(o.v4MessageId);

View on GitHub (pinned to 820761864e)

Solutions

  1. Ensure both writer and reader use the same byte order and framing (ByteBuffer big-endian default).
  2. Verify the position-vector count matches the number of segment entries actually persisted.
  3. Regenerate the blob via toByteArray/from the live checkpoint instead of repairing bytes manually.
  4. Add a length/version header when persisting ids so truncation is detected earlier.

Example fix

// before
byte[] blob = store.load(key); // possibly partial write
MessageIdV5 id = MessageIdV5.fromByteArray(blob);
// after
byte[] blob = store.load(key);
if (blob.length != expectedLen) { // persisted length header
    throw new IOException("Partial blob, discarding checkpoint");
}
MessageIdV5 id = MessageIdV5.fromByteArray(blob);
Defensive patterns

Strategy: validation

Validate before calling

ByteBuffer buf = ByteBuffer.wrap(data);
buf.getLong(); // segmentId
int v4Len = buf.getInt();
buf.position(buf.position() + v4Len);
if (buf.remaining() < 4) {
    throw new IOException("No room for segment-vector count — blob truncated");
}
int count = buf.getInt();
if (8L + 4L * count > buf.remaining()) {
    throw new IOException("Segment vector entries exceed remaining bytes");
}

Try / catch

try {
    MessageIdV5 id = MessageIdV5.fromByteArray(data);
} catch (IOException e) {
    log.warn("Corrupt segment vector, rebuilding positions from broker", e);
}

Prevention

When it happens

Trigger: Deserializing a truncated or offset-shifted blob so the declared id length runs past the buffer end; byte-order mismatch turning the length into a negative/huge value; a count field mismatched with the actual number of entries written.

Common situations: Custom persistence of MessageIdV5 with framing bugs; partial writes from a crashed producer; hand-editing or re-framing checkpoint blobs; mixing little-endian writers with the big-endian ByteBuffer reader.

Related errors


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