QMail Object Abort — Group 6, Code 80
Releases an incomplete transfer and its capacity reservation. The client uses this instead of object_commit when it no longer intends to finish an upload started with object_begin.
Quick reference
| Command Group | 6 |
| Command Code | 80 |
| Server function | cmd_qmail_object_abort in qmail_object_transfer.c |
| Wire structures | qmail_object_abort_req_t, qmail_object_abort_resp_t |
| Body layout | Preamble (48) + Common prefix (16) + transfer_id (16) = 80 bytes request header |
| Transport | TCP only |
| Encryption | Required — AES-128 |
| Idempotent | Yes |
Purpose
A client that decides not to finish an upload — the user cancelled, a fatal local error occurred, the wrong file was selected — should call object_abort rather than simply disconnecting. Abort explicitly marks the transfer aborted, frees the server's in-memory range list for it, and releases the reserved-byte accounting immediately, instead of waiting for the transfer's expiry timer.
Abort only affects the transfer attempt itself; it never touches a previously committed generation of the object. Aborting a replace attempt leaves the object's current live generation exactly as it was before the abandoned object_begin.
Request body
Preamble (48 bytes, offsets 0–47)
Standard QMail preamble. See QMail Overview — Universal preamble.
Common prefix (16 bytes, offsets 48–63)
See object_begin for the shared common-prefix field table. command_header_length must equal 16 for this command.
Abort payload (16 bytes, offsets 64–79)
| Offset | Size | Field | Description |
|---|---|---|---|
| 64–79 | 16 | transfer_id | Must match the transfer_id returned by object_begin for the transfer being abandoned. |
| last 2 | 2 | Terminator | Fixed clear-text terminator. |
Response body
Successful response header length: 48 bytes (16-byte common prefix + 32-byte abort response). No data follows.
| Field | Size | Description |
|---|---|---|
| common_prefix | 16 | Echoes request_id. |
| transfer_id | 16 | Echo of the request's transfer_id. |
| transfer_state | 1 | 3 = aborted. |
| reserved | 15 | Zero. |
Status codes
| Code | Symbol | Meaning |
|---|---|---|
| 250 | SUCCESS | Transfer aborted (or was already aborted — see Idempotency). |
| 218 | ERROR_TCP_REQUIRED | Retry using TCP. |
| 219 | ERROR_UNSUPPORTED_PROTOCOL | Unsupported protocol_version, framing version, or nonzero flags. |
| 222 | ERROR_TRANSFER_NOT_FOUND | transfer_id is unknown for this authenticated owner. |
| 223 | ERROR_TRANSFER_EXPIRED | The transfer already expired on its own before the abort request arrived. |
| 231 | ERROR_OBJECT_STATE | The transfer has already been committed — a committed object cannot be aborted, only replaced or deleted. |
Idempotency
The server retains an aborted-transfer tombstone through the configured terminal-record interval, and at least until the original transfer's expiry, so repeated aborts of the same transfer_id are idempotent and return success rather than ERROR_TRANSFER_NOT_FOUND. Aborting a transfer that has already progressed to committed is rejected with ERROR_OBJECT_STATE rather than silently succeeding, since undoing a published generation is not what abort does.
Common mistakes
Relying on disconnection instead of calling abort
Simply closing the TCP connection without sending abort leaves the transfer's reservation and payment state in place until the configured transfer TTL expires it. If the client intends to give up on an upload, sending an explicit abort frees server capacity immediately rather than after the timeout window.
Expecting abort to undo a commit
Abort only applies to a transfer that has not yet reached committed state. To remove an already-committed object, use object_delete instead.