aeron-io/aeron · error · ClusterException

unable to create node-state file

Error message

unable to create node-state file

What it means

If no NodeStateFile is supplied, conclude() creates one in the cluster directory to persist candidate-term state. An IOException from that file creation (missing/unwritable directory, disk full, leftover file permissions) is wrapped as ClusterException "unable to create node-state file".

Solutions

  1. Ensure the cluster directory exists and is writable by the process user (chown/chmod)
  2. Check free disk space and quotas
  3. Point ctx.clusterDir(...) at a valid writable path
  4. Investigate the cause IOException in the exception chain for the exact OS error

Example fix

// before
ctx.clusterDir(new File("/mnt/readonly/cluster"));
// after
File dir = new File("/var/lib/aeron/cluster");
dir.mkdirs(); // ensure writable
ctx.clusterDir(dir);
Defensive patterns

Strategy: try-catch

Validate before calling

File dir = ctx.clusterDir() != null ? ctx.clusterDir() : new File(ctx.clusterDirectoryName());
if (!dir.isDirectory() || !dir.canWrite()) {
    throw new IllegalStateException("cluster dir not writable: " + dir);
}

Try / catch

try { ctx.conclude(); } catch (ClusterException e) { if ("unable to create node-state file".equals(e.getMessage())) { log.error("check cluster dir permissions/disk", e.getCause()); } }

Prevention

When it happens

Trigger: NodeStateFile constructor throws IOException during conclude() — cluster directory does not exist or is not writable, disk full, or filesystem errors when opening/creating the node state file.

Common situations: clusterDir on a read-only mount or bind-mounted volume with wrong ownership; running in a container as a non-root user without write access to /var/lib/aeron or similar; disk quota exhausted; clusterDir pointing at a file instead of a directory.

Understand the failure class

Background: "failed to write file", "Could not save figure", "Error saving remote file" — file write failed: causes and fixes across languages and libraries — this error's family across 38 libraries.

Related errors


AI-assisted analysis of aeron-io/aeron@6d60124e15 (2026-09-12). Data as JSON: /api/errors/4f9048cd30665bea. Report an issue: GitHub.

Appendix: source

Thrown at aeron-cluster/src/main/java/io/aeron/cluster/ConsensusModule.java:1845

                    epochClock,
                    ClusteredServiceContainer.Configuration.LIVENESS_TIMEOUT_MS,
                    filePageSize);
            }

            MarkFile.ensureMarkFileLink(
                clusterDir,
                new File(markFile.parentDirectory(), ClusterMarkFile.FILENAME),
                ClusterMarkFile.LINK_FILENAME);

            if (null == nodeStateFile)
            {
                try
                {
                    nodeStateFile = new NodeStateFile(clusterDir, true, fileSyncLevel());
                }
                catch (final IOException ex)
                {
                    throw new ClusterException("unable to create node-state file", ex);
                }
            }

            if (Aeron.NULL_VALUE == nodeStateFile.candidateTerm().candidateTermId() &&
                Aeron.NULL_VALUE != markFile.candidateTermId())
            {
                nodeStateFile.updateCandidateTermId(markFile.candidateTermId(), Aeron.NULL_VALUE, epochClock.time());
            }

            if (null == errorLog)
            {
                errorLog = new DistinctErrorLog(markFile.errorBuffer(), epochClock, StandardCharsets.US_ASCII);
            }

            errorHandler = CommonContext.setupErrorHandler(errorHandler, errorLog);

            if (null == recordingLog)
            {

View on GitHub (pinned to 6d60124e15)