aeron-io/aeron · error · ArchiveException

expected schemaId=1055, actual=

Error message

expected schemaId=1055, actual=<schemaId>

What it means

RecordingSignalPoller.onFragment validates each fragment's SBE MessageHeader schemaId against MessageHeaderDecoder.SCHEMA_ID (1055). A differing schemaId means the message does not conform to the Aeron Archive control schema, so the poller refuses to decode and throws ArchiveException including the actual id received.

Solutions

  1. Align aeron-archive-codecs versions between client and archive so schemaId=1055 matches
  2. Confirm the control subscription points at the real archive control channel/stream
  3. Check for custom code writing to the control publication with a different schema
  4. Verify fragments are passed with the original offset and length from the fragment handler

Example fix

// before
directPoller.poll(fragmentHandler); // shared channel with foreign messages
// after
RecordingSignalPoller poller = new RecordingSignalPoller(ctx, subscription, fragmentHandlerLimit);
Defensive patterns

Strategy: try-catch

Validate before calling

MessageHeaderDecoder hdr = new MessageHeaderDecoder().wrap(buffer, offset);
if (hdr.schemaId() != MessageHeaderDecoder.SCHEMA_ID) throw new IllegalStateException("bad schemaId " + hdr.schemaId());

Type guard

boolean hasArchiveSchema(DirectBuffer buffer, int offset) {
    return new MessageHeaderDecoder().wrap(buffer, offset).schemaId() == MessageHeaderDecoder.SCHEMA_ID;
}

Try / catch

try { poller.poll(); }
catch (ArchiveException e) { if (e.getMessage().contains("expected schemaId=")) { reconnectWithMatchingCodecs(); } }

Prevention

When it happens

Trigger: The archive control subscription receives a fragment whose schemaId differs from 1055 — wrong schema generation on the sending side, non-archive traffic on the control stream, or a corrupted frame header.

Common situations: Sender built with a different aeron-archive-codecs version; archive replaced by another service publishing on the same channel/stream; byte corruption or wrong offset injection in custom transport plumbing.

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/855327b10beaf68b. Report an issue: GitHub.

Appendix: source

Thrown at aeron-archive/src/main/java/io/aeron/archive/client/RecordingSignalPoller.java:250

    public String errorMessage()
    {
        return errorMessage;
    }

    ControlledFragmentHandler.Action onFragment(
        final DirectBuffer buffer, final int offset, final int length, final Header header)
    {
        if (isPollComplete)
        {
            return ControlledFragmentHandler.Action.ABORT;
        }

        messageHeaderDecoder.wrap(buffer, offset);

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

        final int templateId = messageHeaderDecoder.templateId();

        if (ControlResponseDecoder.TEMPLATE_ID == templateId)
        {
            controlResponseDecoder.wrap(
                buffer,
                offset + MessageHeaderEncoder.ENCODED_LENGTH,
                messageHeaderDecoder.blockLength(),
                messageHeaderDecoder.version());

            if (controlResponseDecoder.controlSessionId() == controlSessionId)
            {
                this.templateId = templateId;
                correlationId = controlResponseDecoder.correlationId();
                relevantId = controlResponseDecoder.relevantId();
                code = controlResponseDecoder.code();

View on GitHub (pinned to 6d60124e15)