aeron-io/aeron · error · ArchiveException

expected schemaId=

Error message

expected schemaId=

What it means

RecordingEventsPoller.onFragment wraps each fragment's header with MessageHeaderDecoder and requires schemaId == MessageHeaderDecoder.SCHEMA_ID. Any other schemaId means the poller received data that is not an archive recording-event message, so it throws ArchiveException('expected schemaId=..., actual=...') instead of misinterpreting the payload.

Solutions

  1. Ensure the poller subscribes to the correct recording events channel and streamId.
  2. Match Aeron Archive client and archive agent versions (identical SBE schema).
  3. Remove or relocate any other publishers writing to that stream.

Example fix

// before
final RecordingEventsPoller poller = new RecordingEventsPoller(
    ctx.aeron().addSubscription("aeron:udp?endpoint=localhost:9999", 1), // wrong stream
    listener);

// after
final RecordingEventsPoller poller = new RecordingEventsPoller(
    ctx.aeron().addSubscription(eventsChannelUri, recordingEventsStreamId),
    listener);
Defensive patterns

Strategy: try-catch

Try / catch

try {
    while (recordingEventsPoller.poll() == 0 && !isDone()) {
        idleStrategy.idle();
    }
} catch (ArchiveException e) {
    if (e.getMessage().startsWith("expected schemaId=")) {
        // stop polling, verify events channel/streamId and versions
    }
}

Prevention

When it happens

Trigger: Fragment delivered to the poller's subscription whose SBE header schemaId differs from the archive protocol schema — wrong subscription channel/stream, non-archive publisher on the stream, or archive/client built from different schema versions.

Common situations: Sharing the recording events stream with other traffic; version mismatch between the embedded archive client and the archive media driver after dependency upgrade; pointing the poller at a control response channel by mistake.

Related errors


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

Appendix: source

Thrown at aeron-archive/src/main/java/io/aeron/archive/client/RecordingEventsPoller.java:150

    /**
     * {@inheritDoc}
     */
    @Override
    public 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);
        }

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

                recordingId = recordingStartedDecoder.recordingId();
                recordingStartPosition = recordingStartedDecoder.startPosition();
                recordingPosition = recordingStartPosition;
                recordingStopPosition = Aeron.NULL_VALUE;
                isPollComplete = true;
                return ControlledFragmentHandler.Action.BREAK;

View on GitHub (pinned to 6d60124e15)