aeron-io/aeron · error · ClusterException

expected schemaId= , actual=

Error message

expected schemaId=${MessageHeaderDecoder.SCHEMA_ID}, actual=${schemaId}

What it means

ServiceAdapter.onFragment decodes each incoming SBE message beginning with a MessageHeaderDecoder and validates the schemaId against the cluster protocol schema. A mismatch means the fragment is not encoded with the expected cluster-service protocol schema, so it throws this ClusterException rather than misinterpreting the buffer.

Solutions

  1. Run matching Aeron/artifact versions across all cluster nodes (all nodes built from the same aeron-cluster version).
  2. Verify the service is subscribed on the correct consensus module stream and streamId.
  3. Check for corruption or stale data in the cluster/mark file and log directories; clean and re-form the cluster.
  4. Confirm no custom publisher is writing non-cluster messages to this image.

Example fix

// before
// service built against io.aeron:aeron-cluster:1.40 mixing with 1.44 nodes
// after
// align all nodes to the same version, e.g.:
// implementation 'io.aeron:aeron-cluster:1.44.1' in every module
Defensive patterns

Strategy: validation

Validate before calling

// before subscribing/decoding, verify sender version compatibility:
// ensure all nodes use the same aeron-cluster artifact version generating the SBE schema

Try / catch

try {
    serviceAdapter.onFragment(buffer, offset, length, header);
} catch (ClusterException e) {
    if (e.getMessage().contains("expected schemaId=")) {
        // halt and alert: protocol/version mismatch in cluster
    } else {
        throw e;
    }
}

Prevention

When it happens

Trigger: A fragment published on the service adapter's (consensus module -> service) stream whose SBE header schemaId differs from cluster-cluster MessageHeaderDecoder.SCHEMA_ID — e.g. foreign/corrupt data on the channel or a version-incompatible sender.

Common situations: Mixed Aeron versions in one cluster (different generated schema ids); custom protocol extensions sending on the wrong stream; replay/corrupt log data fed to the adapter; connecting a service to the wrong channel/stream-id.

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/1dd736b62723f2e8. Report an issue: GitHub.

Appendix: source

Thrown at aeron-cluster/src/main/java/io/aeron/cluster/service/ServiceAdapter.java:63

    public void close()
    {
        CloseHelper.close(subscription);
    }

    int poll()
    {
        return subscription.poll(fragmentAssembler, FRAGMENT_LIMIT);
    }

    private void onFragment(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);
        }

        switch (messageHeaderDecoder.templateId())
        {
            case JoinLogDecoder.TEMPLATE_ID:
                joinLogDecoder.wrap(
                    buffer,
                    offset + MessageHeaderDecoder.ENCODED_LENGTH,
                    messageHeaderDecoder.blockLength(),
                    messageHeaderDecoder.version());

                clusteredServiceAgent.onJoinLog(
                    joinLogDecoder.logPosition(),
                    joinLogDecoder.maxLogPosition(),
                    joinLogDecoder.memberId(),
                    joinLogDecoder.logSessionId(),
                    joinLogDecoder.logStreamId(),
                    joinLogDecoder.isStartup() == BooleanType.TRUE,

View on GitHub (pinned to 6d60124e15)