aeron-io/aeron · critical · ClusterException
mark file major version <SemanticVersion.major(version)>…
Error message
mark file major version <SemanticVersion.major(version)> does not match software: <MAJOR_VERSION>
What it means
When a ClusterMarkFile already exists on disk, its header's semantic version is checked; if the major version differs from the MAJOR_VERSION the running software expects, a ClusterException is thrown. This prevents a cluster component from running against state files written by an incompatible major release of the format.
Solutions
- Run the same (or format-compatible) Aeron version that created the existing mark file.
- If the old data is disposable, stop the cluster, back up, and delete the stale mark file from the cluster directory.
- Perform a proper upgrade path: drain/stop the old version's cluster cleanly before starting the new version.
Example fix
// before # start v1.40 binary against directory written by v1.30 // after # matching versions mv cluster/cluster-mark-*.mark cluster/backup/ # only if state is expendable # or run the binary version that matches the mark file
Defensive patterns
Strategy: validation
Validate before calling
// java: probe the mark file version before starting the component
try (ClusterMarkFile probe = new ClusterMarkFile(markFile, null, 0, epochClock, logger)) {
int version = probe.version();
if (SemanticVersion.major(version) != ClusterMarkFile.MAJOR_VERSION) {
throw new IllegalStateException("stale mark file, major=" + SemanticVersion.major(version));
}
} catch (NoSuchFileException ignore) { /* fresh start is fine */ } Try / catch
try {
startCluster();
} catch (ClusterException e) {
if (e.getMessage().contains("mark file major version")) {
// stop, archive the old mark file, or redeploy the matching version
}
throw e;
} Prevention
- Pin the Aeron version across all cluster nodes; upgrade the whole cluster in a coordinated operation.
- Back up the cluster directory before any version upgrade.
- Never mix binaries of different major versions in the same cluster directory.
When it happens
Trigger: Starting a consensus module or cluster service over a pre-existing cluster mark file (cluster-mark-0.mark etc.) whose header major version differs from the running binary's MAJOR_VERSION — e.g. after upgrading or downgrading Aeron.
Common situations: Aeron version upgrade without migrating/cleaning the cluster directory; rolling deployments with mixed versions; pointing a new binary at an old replay/archive directory.
Understand the failure class
Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.
Related errors
- incompatible version…
- existing Mark file type
- ClusterMarkFile headerLength=
- invalid errorBufferLength=
- ArchiveMarkFile headerLength=
AI-assisted analysis of aeron-io/aeron@6d60124e15 (2026-09-12).
Data as JSON: /api/errors/236bf5ed3c047b26.
Report an issue: GitHub.
Appendix: source
Thrown at aeron-cluster/src/main/java/io/aeron/cluster/service/ClusterMarkFile.java:169
{
final int currentHeaderOffset = headerOffset(file);
final MarkFile existingMarkFile = new MarkFile(
file,
true,
currentHeaderOffset + MarkFileHeaderDecoder.versionEncodingOffset(),
currentHeaderOffset + MarkFileHeaderDecoder.activityTimestampEncodingOffset(),
totalFileLength,
timeoutMs,
epochClock,
(version) ->
{
if (VERSION_FAILED == version)
{
System.err.println("mark file version -1 indicates error on previous startup.");
}
else if (SemanticVersion.major(version) != MAJOR_VERSION)
{
throw new ClusterException("mark file major version " + SemanticVersion.major(version) +
" does not match software: " + MAJOR_VERSION);
}
},
null);
final UnsafeBuffer existingBuffer = existingMarkFile.buffer();
if (0 != currentHeaderOffset)
{
headerDecoder.wrapAndApplyHeader(existingBuffer, 0, messageHeaderDecoder);
}
else
{
headerDecoder.wrap(
existingBuffer, 0, MarkFileHeaderDecoder.BLOCK_LENGTH, MarkFileHeaderDecoder.SCHEMA_VERSION);
}
final ClusterComponentType existingType = headerDecoder.componentType();
if (existingType != ClusterComponentType.UNKNOWN && existingType != type)View on GitHub (pinned to 6d60124e15)