aeron-io/aeron · error · ArchiveException
expected schemaId=
Error message
expected schemaId=
What it means
RecordingDescriptorPoller.onFragment wraps the incoming SBE buffer in a MessageHeaderDecoder and verifies the SBE schemaId matches the archive protocol schema. A mismatch means the fragment is not an archive control-protocol message (wrong channel, corrupted frame, or a different SBE schema version), so ArchiveException('expected schemaId=..., actual=...') is thrown.
Solutions
- Use matching Aeron Archive client and server versions (same SBE schema).
- Point the poller's subscription at the archive control response channel/stream it was designed for.
- Verify the stream is not shared with other publishers sending non-archive messages.
Example fix
// before // poller subscribed to a stream fed by a different Aeron Archive version archive.listRecording(subscription, poller, recordingId); // ArchiveException: expected schemaId=... // after // align versions in pom.xml // <dependency><artifactId>aeron-archive</artifactId><version>X.Y.Z</version></dependency> // <dependency><artifactId>aeron-driver</artifactId><version>X.Y.Z</version></dependency>
Defensive patterns
Strategy: try-catch
Try / catch
try {
archive.listRecording(recordingId, recordingDescriptorPoller);
} catch (ArchiveException e) {
if (e.getMessage().startsWith("expected schemaId=")) {
// wrong stream content or schema version mismatch: reconnect/upgrade
}
} Prevention
- Pin aeron-archive and aeron-driver to the same release version.
- Do not share the archive control response stream with other publishers.
When it happens
Trigger: A fragment arrives on the subscription used by RecordingDescriptorPoller whose header schemaId differs from MessageHeaderDecoder.SCHEMA_ID — e.g. the poller was pointed at a channel carrying non-archive data, or client/server archive SBE schema versions differ.
Common situations: Subscribing the descriptor poller to the wrong stream/channel; mixing Aeron client and archive versions (protocol schema changed between releases); garbage from a misconfigured shared endpoint.
Related errors
- expected schemaId=
- expected schemaId=
- expected schemaId=
- expected schemaId=
- expected schemaId=" + MessageHeaderDecoder.SCHEMA_ID + "…
AI-assisted analysis of aeron-io/aeron@6d60124e15 (2026-09-12).
Data as JSON: /api/errors/a80b3e61152e74bd.
Report an issue: GitHub.
Appendix: source
Thrown at aeron-archive/src/main/java/io/aeron/archive/client/RecordingDescriptorPoller.java:176
this.remainingRecordCount = recordCount;
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.RECORDING_UNKNOWN == code && responseCorrelationId == correlationId)View on GitHub (pinned to 6d60124e15)