aeron-io/aeron · critical · ClusterException
expected schemaId= , actual=
Error message
expected schemaId=<SCHEMA_ID>, actual=<schemaId>
What it means
In ConsensusModuleAgent's replay/fragment handling, after dispatching to message decoders the agent verifies the SBE header schema id matched MessageHeaderDecoder.SCHEMA_ID; otherwise it throws. This protects log replay from decoding messages written with a different cluster protocol schema.
Solutions
- Ensure all cluster nodes run the same Aeron version so log schema ids are identical.
- Verify nothing external is publishing to the cluster log channel.
- Rebuild the cluster from a snapshot/archives produced with the current schema version.
- Clean the classpath of duplicate/old aeron-cluster codec artifacts.
Example fix
// before: node upgraded alone, log schema differs // after: stop all nodes, snapshot, upgrade every node, restart
Defensive patterns
Strategy: try-catch
Try / catch
try { cluster.start(); } catch (ClusterException e) { if (e.getMessage().contains("expected schemaId")) { rebuildFromSnapshotWithCurrentSchema(); } else { throw e; } } Prevention
- Upgrade all nodes together after taking a snapshot.
- Keep the log channel private to the cluster.
- Avoid mixing codec artifacts from different Aeron releases.
When it happens
Trigger: During log or snapshot replay, a fragment's messageHeaderDecoder.schemaId() is not MessageHeaderDecoder.SCHEMA_ID, so none of the decoder branches handle it and the fallback throw is reached.
Common situations: Replaying a log produced by a different Aeron version with a changed cluster SBE schema; mixed-version cluster membership; corrupt log buffer contents from an external writer on the log channel.
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= , actual=
- expected schemaId= , actual=
- expected cluster egress…
- expected schemaId= , actual=
- snapshot ended unexpectedly
AI-assisted analysis of aeron-io/aeron@6d60124e15 (2026-09-12).
Data as JSON: /api/errors/d573e38c1e885d26.
Report an issue: GitHub.
Appendix: source
Thrown at aeron-cluster/src/main/java/io/aeron/cluster/ConsensusModuleAgent.java:1536
final Header header)
{
if (null != consensusModuleExtension)
{
final int remainingMessageOffset = offset + MessageHeaderDecoder.ENCODED_LENGTH;
final int remainingMessageLength = length - MessageHeaderDecoder.ENCODED_LENGTH;
return consensusModuleExtension.onLogExtensionMessage(
actingBlockLength,
templateId,
schemaId,
actingVersion,
buffer,
remainingMessageOffset,
remainingMessageLength,
header);
}
throw new ClusterException("expected schemaId=" + MessageHeaderDecoder.SCHEMA_ID + ", actual=" + schemaId);
}
void onReplayTimerEvent(final long correlationId)
{
if (!timerService.cancelTimerByCorrelationId(correlationId))
{
expiredTimerCountByCorrelationIdMap.getAndIncrement(correlationId);
}
}
void onReplaySessionOpen(
final long logPosition,
final long correlationId,
final long clusterSessionId,
final long timestamp,
final int responseStreamId,
final String responseChannel)
{View on GitHub (pinned to 6d60124e15)