{"record":{"id":"912e498b00bbbae2","repo":"aeron-io/aeron","slug":"failed-to-send-detach-segments-request","errorCode":null,"errorMessage":"failed to send detach segments request","messagePattern":"failed to send detach segments request","errorType":"exception","errorClass":"ArchiveException","httpStatus":null,"severity":"error","filePath":"aeron-archive/src/main/java/io/aeron/archive/client/AeronArchive.java","lineNumber":2167,"sourceCode":"     * It is not possible to detach segments which are active for recording or being replayed.\n     *\n     * @param recordingId      to which the operation applies.\n     * @param newStartPosition for the recording after the segments are detached.\n     * @see #segmentFileBasePosition(long, long, int, int)\n     */\n    public void detachSegments(final long recordingId, final long newStartPosition)\n    {\n        lock.lock();\n        try\n        {\n            ensureConnected();\n            ensureNotReentrant();\n\n            lastCorrelationId = aeron.nextCorrelationId();\n\n            if (!archiveProxy.detachSegments(recordingId, newStartPosition, lastCorrelationId, controlSessionId))\n            {\n                throw new ArchiveException(\"failed to send detach segments request\");\n            }\n\n            pollForResponse(lastCorrelationId);\n        }\n        finally\n        {\n            lock.unlock();\n        }\n    }\n\n    /**\n     * Delete segments which have been previously detached from a recording.\n     *\n     * @param recordingId to which the operation applies.\n     * @return count of deleted segment files.\n     * @see #detachSegments(long, long)\n     */\n    public long deleteDetachedSegments(final long recordingId)","sourceCodeStart":2149,"sourceCodeEnd":2185,"githubUrl":"https://github.com/aeron-io/aeron/blob/6d60124e15e35c11b49ba2e3c2c2858a09a18803/aeron-archive/src/main/java/io/aeron/archive/client/AeronArchive.java#L2149-L2185","documentation":"Thrown when a detachSegments request could not be offered to the archive control publication. ArchiveProxy.detachSegments returned false after retries, so the archive never received the instruction to detach segments at newStartPosition. No storage change occurred; this is a request-delivery failure on the control channel.","triggerScenarios":"Calling AeronArchive.detachSegments(recordingId, newStartPosition) while the control session publication is closed, the archive is unreachable, or the publication is back-pressured beyond the offer retry limit.","commonSituations":"Storage-management jobs running against an archive that restarted; long-lived housekeeping clients whose sessions timed out; control channel congestion while other archive operations (truncates, purges) run concurrently.","solutions":["Reconnect the archive session (AeronArchive.connect) and retry detachSegments.","Verify the archive process and control channel are healthy (logs, error counters) before retrying.","Stagger storage-maintenance operations to avoid control-channel back-pressure.","Reduce session idle time between operations or raise the archive session timeout for maintenance clients.","Confirm the recordingId exists before the call so that a subsequent failure is not confused with a resource problem (this specific error is delivery, not the recording)."],"exampleFix":"// before\narchive.detachSegments(recordingId, newStartPosition);\n// after\ntry {\n    archive.detachSegments(recordingId, newStartPosition);\n} catch (ArchiveException e) {\n    if (e.message().contains(\"failed to send\")) {\n        archive = AeronArchive.connect(ctx);\n        archive.detachSegments(recordingId, newStartPosition);\n    } else {\n        throw e;\n    }\n}","handlingStrategy":"try-catch","validationCode":"if (archive == null || archive.context().isClosed()) { archive = AeronArchive.connect(ctx); }","typeGuard":"static boolean isSendFailure(ArchiveException e) { return e.getMessage() != null && e.getMessage().contains(\"failed to send\"); }","tryCatchPattern":"try { archive.detachSegments(recordingId, newStartPosition); } catch (ArchiveException e) { if (isSendFailure(e)) { archive = AeronArchive.connect(ctx); archive.detachSegments(recordingId, newStartPosition); } else { throw e; } }","preventionTips":["Validate the recordingId and newStartPosition against the catalog before the call, so send failures stay distinguishable from resource errors.","Stagger storage maintenance operations to avoid control-channel congestion.","Keep maintenance sessions alive or recreate them per job run.","Monitor archive uptime and reconnect after restarts before housekeeping."],"tags":["aeron-archive","segments","control-session","ipc-offer-failed"],"backgroundTag":"api-request-failed","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"}