{"record":{"id":"2aed2e95dd64ed80","repo":"aeron-io/aeron","slug":"response-publication-already-added","errorCode":null,"errorMessage":"response publication already added","messagePattern":"response publication already added","errorType":"exception","errorClass":"ClusterException","httpStatus":null,"severity":"error","filePath":"aeron-cluster/src/main/java/io/aeron/cluster/ClusterSession.java","lineNumber":204,"sourceCode":"        closedLogPosition = AeronArchive.NULL_POSITION;\n        closeReason = CloseReason.NULL_VAL;\n    }\n\n    void asyncConnect(final Aeron aeron, final MutableDirectBuffer tempBuffer, final int clusterId)\n    {\n        counterRegistrationId = addSessionCounter(aeron, tempBuffer, clusterId);\n        responsePublicationId = aeron.asyncAddPublication(responseChannel, responseStreamId);\n    }\n\n    void connect(\n        final ErrorHandler errorHandler,\n        final Aeron aeron,\n        final MutableDirectBuffer tempBuffer,\n        final int clusterId)\n    {\n        if (null != responsePublication)\n        {\n            throw new ClusterException(\"response publication already added\");\n        }\n\n        counterRegistrationId = addSessionCounter(aeron, tempBuffer, clusterId);\n\n        try\n        {\n            responsePublication = aeron.addPublication(responseChannel, responseStreamId);\n        }\n        catch (final RegistrationException ex)\n        {\n            errorHandler.onError(new ClusterException(\n                \"failed to connect session response publication: \" + ex.getMessage(), AeronException.Category.WARN));\n        }\n    }\n\n    void disconnect(final Aeron aeron, final ErrorHandler errorHandler)\n    {\n        if (NULL_VALUE != responsePublicationId)","sourceCodeStart":186,"sourceCodeEnd":222,"githubUrl":"https://github.com/aeron-io/aeron/blob/6d60124e15e35c11b49ba2e3c2c2858a09a18803/aeron-cluster/src/main/java/io/aeron/cluster/ClusterSession.java#L186-L222","documentation":"ClusterSession.connect creates the response publication wiring for a clustered session, but refuses to run if a responsePublication was already set. This is an internal lifecycle invariant: a session must not be connected twice, otherwise a second publication would be added for the same session and the first would leak.","triggerScenarios":"Calling connect(aeron, tempBuffer, clusterId) on a ClusterSession whose responsePublication field is non-null. In practice this happens when prepareSessionsForNewTerm runs connect on sessions that were not correctly disconnected/reset between terms.","commonSituations":"Cluster recovery or term-rollover paths where the previous term's sessions were not closed; a bug in lifecycle management when replaying/reusing sessions across leadership changes; custom code reusing a ClusterSession instance.","solutions":["Ensure sessions from the previous term are closed/disconnected before calling connect again.","Check the prepareSessionsForNewTerm path only calls connect for sessions with a null responsePublication (sessions that need reconnection).","If managing sessions directly, null out or discard the old session object and create a fresh one instead of reusing it.","Report to Aeron maintainers if this occurs on the stock recovery path, as it indicates an internal invariant break."],"exampleFix":"// before\nsession.connect(aeron, tempBuffer, clusterId); // session already connected\n// after\nif (null == session.responsePublication())\n{\n    session.connect(aeron, tempBuffer, clusterId);\n}","handlingStrategy":"type-guard","validationCode":"if (null != session.responsePublication()) { /* session already connected */ }","typeGuard":"boolean isConnectable(ClusterSession s) { return null == s.responsePublication(); }","tryCatchPattern":"try\n{\n    session.connect(aeron, tempBuffer, clusterId);\n}\ncatch (ClusterException ex)\n{\n    if (!ex.getMessage().contains(\"response publication already added\")) throw ex;\n    // fall through: session already connected\n}","preventionTips":["Only call connect on sessions created fresh for the new term.","Track session lifecycle state explicitly in code managing sessions across terms.","Always disconnect/close sessions before reusing them."],"tags":["aeron","cluster","lifecycle","invariant"],"backgroundTag":"invalid-state-transition","analyzedSha":"6d60124e15e35c11b49ba2e3c2c2858a09a18803","analyzedAt":"2026-09-12T11:17:07.683Z","contentChangedAt":"2026-09-12T11:17:07.683Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}