aeron-io/aeron · error · ArchiveException
failed to send detach segments request
Error message
failed to send detach segments request
What it means
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.
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).
Example fix
// before
archive.detachSegments(recordingId, newStartPosition);
// after
try {
archive.detachSegments(recordingId, newStartPosition);
} catch (ArchiveException e) {
if (e.message().contains("failed to send")) {
archive = AeronArchive.connect(ctx);
archive.detachSegments(recordingId, newStartPosition);
} else {
throw e;
}
} Defensive patterns
Strategy: try-catch
Validate before calling
if (archive == null || archive.context().isClosed()) { archive = AeronArchive.connect(ctx); } Type guard
static boolean isSendFailure(ArchiveException e) { return e.getMessage() != null && e.getMessage().contains("failed to send"); } Try / catch
try { archive.detachSegments(recordingId, newStartPosition); } catch (ArchiveException e) { if (isSendFailure(e)) { archive = AeronArchive.connect(ctx); archive.detachSegments(recordingId, newStartPosition); } else { throw e; } } Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: "API request failed": what wrapped HTTP errors from external APIs mean and how to find the real cause — this error's family across 29 libraries.
Related errors
- failed to send invalidate recording request
- failed to send list recording subscriptions request
- failed to send replicate request
- failed to send tagged replicate request
- failed to send stop replication request
AI-assisted analysis of aeron-io/aeron@6d60124e15 (2026-09-12).
Data as JSON: /api/errors/912e498b00bbbae2.
Report an issue: GitHub.
Appendix: source
Thrown at aeron-archive/src/main/java/io/aeron/archive/client/AeronArchive.java:2167
* It is not possible to detach segments which are active for recording or being replayed.
*
* @param recordingId to which the operation applies.
* @param newStartPosition for the recording after the segments are detached.
* @see #segmentFileBasePosition(long, long, int, int)
*/
public void detachSegments(final long recordingId, final long newStartPosition)
{
lock.lock();
try
{
ensureConnected();
ensureNotReentrant();
lastCorrelationId = aeron.nextCorrelationId();
if (!archiveProxy.detachSegments(recordingId, newStartPosition, lastCorrelationId, controlSessionId))
{
throw new ArchiveException("failed to send detach segments request");
}
pollForResponse(lastCorrelationId);
}
finally
{
lock.unlock();
}
}
/**
* Delete segments which have been previously detached from a recording.
*
* @param recordingId to which the operation applies.
* @return count of deleted segment files.
* @see #detachSegments(long, long)
*/
public long deleteDetachedSegments(final long recordingId)View on GitHub (pinned to 6d60124e15)