aeron-io/aeron · critical · ClusterException
mark file major version
Error message
mark file major version ${version} does not match software: ${majorVersion} What it means
NodeStateFile.loadInitialState validates the SBE-encoded header of the node-state file: its major version must match ClusterMarkFile.MAJOR_VERSION of the installed Aeron software. A file written by an incompatible Aeron version is rejected with this ClusterException.
Solutions
- Use the Aeron version that matches the file's major version to read/migrate the state
- Delete (after backup) the node-state file and let the new version recreate it via createNew=true
- Migrate state by reading the file with the old version and re-writing it with the new version
- If the file was corrupted (version field nonsense), restore from backup
Example fix
// before: reusing old cluster dir after major upgrade NodeStateFile f = new NodeStateFile(clusterDir, false); // after: recreate the file under the new major version new File(clusterDir, NodeStateFile.FILENAME).delete(); NodeStateFile f = new NodeStateFile(clusterDir, true);
Defensive patterns
Strategy: validation
Validate before calling
int version = readHeaderVersion(buffer); if (SemanticVersion.major(version) != ClusterMarkFile.MAJOR_VERSION) { /* migrate or recreate */ } Try / catch
try { f = new NodeStateFile(clusterDir, false); } catch (ClusterException e) { /* recreate file with matching version */ } Prevention
- Don't reuse cluster dirs across major Aeron upgrades without migration
- Pin the same Aeron version across environments
- Back up state files before upgrading
When it happens
Trigger: Opening a node-state file created by a different Aeron major version (upgrade or downgrade of the Aeron driver/cluster across incompatible versions), or a file whose header version field is corrupted.
Common situations: Rolling upgrades where the cluster dir is reused across a major version jump; copying cluster state files between environments with different Aeron versions; corrupted file from a partial write/crash.
Related errors
- expected schemaId= , actual=
- failed to find NodeStateFooter entry, file corrupt?
- NodeStateFile does not exist and createNew=false
- AERON_ERROR_CODE_UNKNOWN_COMMAND_TYPE_ID
- already in snapshot
AI-assisted analysis of aeron-io/aeron@6d60124e15 (2026-09-12).
Data as JSON: /api/errors/c6083e0be421ef28.
Report an issue: GitHub.
Appendix: source
Thrown at aeron-cluster/src/main/java/io/aeron/cluster/NodeStateFile.java:178
{
throw new IllegalStateException(
"offset=" + offset + " is not correctly aligned, it is not divisible by " + ALIGNMENT);
}
}
private static void loadInitialState(
final MutableDirectBuffer buffer,
final NodeStateHeaderDecoder nodeStateHeaderDecoder,
final CandidateTermDecoder candidateTermDecoder,
final MessageHeaderDecoder messageHeaderDecoder)
{
nodeStateHeaderDecoder.wrap(
buffer, 0, NodeStateHeaderDecoder.BLOCK_LENGTH, NodeStateHeaderDecoder.SCHEMA_VERSION);
final int version = nodeStateHeaderDecoder.version();
if (ClusterMarkFile.MAJOR_VERSION != SemanticVersion.major(version))
{
throw new ClusterException(
"mark file major version " + SemanticVersion.major(version) +
" does not match software: " + ClusterMarkFile.MAJOR_VERSION);
}
final int footerOffset = scanForMessageTypeOffset(
nodeStateHeaderDecoder.sbeBlockLength(),
NodeStateFooterDecoder.TEMPLATE_ID,
buffer,
messageHeaderDecoder);
if (Aeron.NULL_VALUE == footerOffset)
{
throw new IllegalStateException("failed to find NodeStateFooter entry, file corrupt?");
}
final int candidateTermOffset = scanForMessageTypeOffset(
nodeStateHeaderDecoder.sbeBlockLength(),
CandidateTermDecoder.TEMPLATE_ID,View on GitHub (pinned to 6d60124e15)