aeron-io/aeron · error · ArchiveException
expected schemaId=1055, actual=
Error message
expected schemaId=1055, actual=<schemaId>
What it means
RecordingSubscriptionDescriptorPoller.onFragment checks each fragment's SBE MessageHeader schemaId against MessageHeaderDecoder.SCHEMA_ID (1055) before dispatching on templateId. A mismatch means the fragment is not an Archive control-protocol message and cannot be safely decoded, so ArchiveException is thrown with the actual schemaId.
Solutions
- Use the same aeron-archive version on archive and client so SBE schema ids match
- Dedicate the control channel/stream to archive control traffic
- Confirm listRecordingSubscriptions targets the correct archive control channel
- Validate no manual offset manipulation occurs before messageHeaderDecoder.wrap
Example fix
// before: mixed versions <dependency io.aeron:aeron-client:1.40.0> + archive 1.44.0 // after: aligned versions <dependency io.aeron:aeron-client:1.44.0> + <dependency io.aeron:aeron-archive:1.44.0>
Defensive patterns
Strategy: try-catch
Validate before calling
MessageHeaderDecoder hdr = new MessageHeaderDecoder().wrap(buffer, offset); assert hdr.schemaId() == MessageHeaderDecoder.SCHEMA_ID : "schema mismatch: " + hdr.schemaId();
Type guard
boolean isArchiveControlFragment(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("schemaId")) { log.error("codec version mismatch", e); } } Prevention
- Align aeron-archive versions between client and archive
- Dedicate the archive control channel to archive traffic only
- Log the actual schemaId to identify the foreign schema quickly
When it happens
Trigger: Fragments on the control subscription used to list recording subscriptions carry a schemaId other than 1055 — codec version mismatch, foreign publisher on the control stream, or wrong stream wiring.
Common situations: Upgrading Aeron partially (client new, archive old or vice versa); reusing a control channel also used by an application publisher; custom tooling replaying foreign messages into the stream.
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
- expected schemaId=
- expected schemaId=1055, actual=
- expected schemaId=
- expected schemaId=
- expected schemaId=
AI-assisted analysis of aeron-io/aeron@6d60124e15 (2026-09-12).
Data as JSON: /api/errors/5cdd5756b9f17bd7.
Report an issue: GitHub.
Appendix: source
Thrown at aeron-archive/src/main/java/io/aeron/archive/client/RecordingSubscriptionDescriptorPoller.java:182
this.remainingSubscriptionCount = subscriptionCount;
isDispatchComplete = false;
}
@SuppressWarnings("MethodLength")
ControlledFragmentAssembler.Action onFragment(
final DirectBuffer buffer, final int offset, final int length, final Header header)
{
if (isDispatchComplete)
{
return ControlledFragmentAssembler.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();
switch (templateId)
{
case ControlResponseDecoder.TEMPLATE_ID:
controlResponseDecoder.wrap(
buffer,
offset + MessageHeaderEncoder.ENCODED_LENGTH,
messageHeaderDecoder.blockLength(),
messageHeaderDecoder.version());
if (controlResponseDecoder.controlSessionId() == controlSessionId)
{
final ControlResponseCode code = controlResponseDecoder.code();
final long responseCorrelationId = controlResponseDecoder.correlationId();
if (ControlResponseCode.SUBSCRIPTION_UNKNOWN == code && responseCorrelationId == correlationId)View on GitHub (pinned to 6d60124e15)