aeron-io/aeron · error · ClusterException

publication is closed

Error message

publication is closed

What it means

ConsensusModuleProxy.checkResult throws this when a publication operation returns Publication.CLOSED, meaning the publication to the consensus module has been closed (e.g. during shutdown or after an error). Further offers via scheduleTimer/cancelTimer/offer/tryClaim/ack/closeSession cannot succeed.

Solutions

  1. Stop using the proxy once the container/service is closing; guard calls with an isClosing/isShutdown flag.
  2. Treat this as terminal: rethrow or log and end the service duty cycle rather than retrying.
  3. Verify shutdown ordering: close ClusteredServiceAgent before closing publications it uses.
  4. Check for a root cause that closed the publication (e.g. earlier ClusterException in the consensus module log).

Example fix

// before
proxy.ack(logPosition, timestamp, sessionId, serviceId);
// after
if (!isClosing && !proxy.ack(logPosition, timestamp, sessionId, serviceId)) {
    // handle not-offered/closed
}
Defensive patterns

Strategy: try-catch

Try / catch

try {
    proxy.ack(logPosition, timestamp, sessionId, serviceId);
} catch (ClusterException e) {
    if (e.getMessage().contains("publication is closed")) {
        // terminal: stop issuing calls, initiate shutdown/cleanup
    } else {
        throw e;
    }
}

Prevention

When it happens

Trigger: Invoking any ConsensusModuleProxy method (scheduleTimer, cancelTimer, offer, tryClaim, ack, closeSession) after the consensus module publication was closed, typically during orderly or abnormal cluster shutdown.

Common situations: Service continuing to ack or schedule timers after container shutdown begun; consensus module crashed and closed the channel; close() raced with an in-flight agent duty cycle call.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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

Appendix: source

Thrown at aeron-cluster/src/main/java/io/aeron/cluster/service/ConsensusModuleProxy.java:228

            return true;
        }

        checkResult(position, publication);

        return false;
    }

    private static void checkResult(final long position, final Publication publication)
    {
        if (Publication.NOT_CONNECTED == position)
        {
            throw new ClusterException("publication is not connected");
        }

        if (Publication.CLOSED == position)
        {
            throw new ClusterException("publication is closed");
        }

        if (Publication.MAX_POSITION_EXCEEDED == position)
        {
            throw new ClusterException("publication at max position: term-length=" + publication.termBufferLength());
        }
    }
}

View on GitHub (pinned to 6d60124e15)