{"record":{"id":"6f3b2dcab518bec6","repo":"aeron-io/aeron","slug":"failed-to-send-truncate-recording-request","errorCode":null,"errorMessage":"failed to send truncate recording request","messagePattern":"failed to send truncate recording request","errorType":"exception","errorClass":"ArchiveException","httpStatus":null,"severity":"error","filePath":"aeron-archive/src/main/java/io/aeron/archive/client/AeronArchive.java","lineNumber":1691,"sourceCode":"     * Truncating a recording will stop any concurrent replays of that recording.\n     *\n     * @param recordingId of the stopped recording to be truncated.\n     * @param position    to which the recording will be truncated.\n     * @return count of deleted segment files.\n     */\n    public long truncateRecording(final long recordingId, final long position)\n    {\n        lock.lock();\n        try\n        {\n            ensureConnected();\n            ensureNotReentrant();\n\n            lastCorrelationId = aeron.nextCorrelationId();\n\n            if (!archiveProxy.truncateRecording(recordingId, position, lastCorrelationId, controlSessionId))\n            {\n                throw new ArchiveException(\"failed to send truncate recording request\");\n            }\n\n            return pollForResponse(lastCorrelationId);\n        }\n        finally\n        {\n            lock.unlock();\n        }\n    }\n\n\n    /**\n     * Purge a stopped recording, i.e. mark recording as {@link io.aeron.archive.codecs.RecordingState#INVALID}\n     * and delete the corresponding segment files. The space in the Catalog will be reclaimed upon compaction.\n     *\n     * @param recordingId of the stopped recording to be purged.\n     * @return count of deleted segment files.\n     */","sourceCodeStart":1673,"sourceCodeEnd":1709,"githubUrl":"https://github.com/aeron-io/aeron/blob/6d60124e15e35c11b49ba2e3c2c2858a09a18803/aeron-archive/src/main/java/io/aeron/archive/client/AeronArchive.java#L1673-L1709","documentation":"AeronArchive.truncateRecording() throws this ArchiveException when the truncate-recording request could not be offered to the archive control-request publication. archiveProxy.truncateRecording() returned false, meaning the message was not enqueued (publication not connected, closed, or back-pressured for the entire retry window), so pollForResponse never runs and the recording is not truncated.","triggerScenarios":"Calling truncateRecording(recordingId, position) when the archive control stream cannot accept the request: archive process down, control session expired or closed by the archive, control-request terminal buffer full, or misconfigured control channel.","commonSituations":"Rewinding a recording to re-consume it while the archive is restarting; long-lived clients whose session was reaped; truncation issued right after a failed replay request that already saturated the control stream.","solutions":["Check that the archive is up and control-channel configuration matches on client and archive.","Retry truncateRecording after a short backoff; transient back-pressure frequently clears.","Reconnect with AeronArchive.connect() if the control session has been closed server-side.","Ensure the recording is stopped and the position is a valid stop position before retrying, so repeated failed offers do not keep filling the buffer.","Inspect archive logs for session timeouts or publication errors preceding this failure."],"exampleFix":"// before\narchive.truncateRecording(recordingId, position);\n\n// after\ntry {\n    archive.truncateRecording(recordingId, position);\n} catch (ArchiveException e) {\n    if (e.getMessage().contains(\"failed to send truncate recording request\")) {\n        // archive unreachable or control session dead; reconnect and retry\n        try (AeronArchive fresh = AeronArchive.connect(ctx)) {\n            fresh.truncateRecording(recordingId, position);\n        }\n    } else {\n        throw e;\n    }\n}","handlingStrategy":"retry","validationCode":"// ensure the recording is stopped and control channel is connected before truncating\nif (!archive.archiveProxy().controlPublication().isConnected()) {\n    throw new IllegalStateException(\"archive control publication not connected\");\n}\nlong stopPos = archive.getStopPosition(recordingId);\nif (position < 0 || position > stopPos) {\n    throw new IllegalArgumentException(\"truncate position out of range: \" + position);\n}","typeGuard":null,"tryCatchPattern":"try {\n    archive.truncateRecording(recordingId, position);\n} catch (ArchiveException e) {\n    if (e.getMessage().contains(\"failed to send truncate recording request\")) {\n        Thread.sleep(backoffMs); // reconnect if the session is dead, then retry\n    } else { throw e; }\n}","preventionTips":["Stop the recording and validate the truncate position before issuing the request.","Check control-publication connectivity before destructive operations.","Retry with backoff and reconnect on session loss.","Avoid chaining truncate right after failed requests that may have saturated the control stream."],"tags":["aeron-archive","backpressure","control-channel","truncate"],"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"}