aeron-io/aeron · error · ClusterException

expected schemaId=<MessageHeaderDecoder.SCHEMA_ID>, actual=

Error message

expected schemaId=<MessageHeaderDecoder.SCHEMA_ID>, actual=<schemaId>

What it means

BoundedLogAdapter.onMessage wraps the SBE MessageHeader of a replay/log fragment and checks schemaId against MessageHeaderDecoder.SCHEMA_ID; a mismatch means the fragment is not from the cluster's log schema, so ClusterException is thrown (from onFragment). Decoding with mismatched codecs would corrupt state.

Solutions

  1. Ensure all cluster nodes and services use the same aeron-cluster version
  2. Verify the adapter subscription targets the cluster log stream only
  3. Regenerate codecs from the correct schema version if customized
  4. Confirm replay logs come from a compatible Aeron release

Example fix

// before
// node on aeron-cluster 1.40 joining cluster of 1.44 nodes
// after
// upgrade node to 1.44 so log schemaIds match
Defensive patterns

Strategy: try-catch

Validate before calling

MessageHeaderDecoder h = new MessageHeaderDecoder().wrap(buffer, offset);
if (h.schemaId() != MessageHeaderDecoder.SCHEMA_ID) {
    throw new IllegalStateException("incompatible log schema: " + h.schemaId());
}

Try / catch

try {
    adapter.onFragment(buffer, offset, length, header);
} catch (ClusterException ex) {
    // abort replay; check version skew
}

Prevention

When it happens

Trigger: Recording/replay adapters attached to an image whose stream uses a different SBE schema; cluster components built with mismatched aeron-cluster versions sharing a log/archive channel.

Common situations: Mixed Aeron versions between nodes in a cluster; custom services publishing onto the log channel; replaying a log from an incompatible version.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


AI-assisted analysis of aeron-io/aeron@6d60124e15 (2026-09-12). Data as JSON: /api/errors/601cde6f856da548. Report an issue: GitHub.

Appendix: source

Thrown at aeron-cluster/src/main/java/io/aeron/cluster/service/BoundedLogAdapter.java:143

    Image image()
    {
        return image;
    }

    int poll(final long limit)
    {
        return image.boundedControlledPoll(this, limit, fragmentLimit);
    }

    @SuppressWarnings("MethodLength")
    private Action onMessage(final DirectBuffer buffer, final int offset, final int length, final Header header)
    {
        messageHeaderDecoder.wrap(buffer, offset);

        final int schemaId = messageHeaderDecoder.schemaId();
        if (schemaId != MessageHeaderDecoder.SCHEMA_ID)
        {
            throw new ClusterException("expected schemaId=" + MessageHeaderDecoder.SCHEMA_ID + ", actual=" + schemaId);
        }

        final int templateId = messageHeaderDecoder.templateId();
        if (templateId == SessionMessageHeaderDecoder.TEMPLATE_ID)
        {
            sessionHeaderDecoder.wrap(
                buffer,
                offset + MessageHeaderDecoder.ENCODED_LENGTH,
                messageHeaderDecoder.blockLength(),
                messageHeaderDecoder.version());

            agent.onSessionMessage(
                header.position(),
                sessionHeaderDecoder.clusterSessionId(),
                sessionHeaderDecoder.timestamp(),
                buffer,
                offset + AeronCluster.SESSION_HEADER_LENGTH,
                length - AeronCluster.SESSION_HEADER_LENGTH,

View on GitHub (pinned to 6d60124e15)