SyncEngine Protocol v1 — Error Codes
Numeric values carried in ERROR (field 1) and TRANSFER_CANCEL (field 2). Codes are stable once published; a removed code is never reassigned.
"Wire" indicates whether the code can be sent to a peer. Codes marked "local" are only reported to the local user or API, e.g. because the session can no longer carry encrypted messages.
| Code | Name | Wire | Typical use |
|---|---|---|---|
| Session / protocol (1–99) | |||
| 1 | E_PROTOCOL_VERSION | yes | HELLO.protocol_major mismatch or detected version downgrade |
| 2 | E_PROTOCOL_VIOLATION | yes | Malformed frame/CBOR, wrong stream, wrong direction, sequence error |
| 3 | E_UNKNOWN_MESSAGE | yes | Unknown message type |
| 4 | E_UNSUPPORTED_CRITICAL | yes | Unknown critical capability |
| 5 | E_FRAME_TOO_LARGE | yes | Frame length above effective max_frame_payload |
| 6 | E_LIMIT_EXCEEDED | yes | Stream limit, capability floor, clipboard size |
| 7 | E_TIMEOUT | yes | Handshake, session establishment, pairing confirmation |
| 8 | E_DUPLICATE_SESSION | yes | Losing session of a duplicate pair |
| Authentication / pairing (100–199) | |||
| 100 | E_AUTH_FAILED | local | Noise handshake or record authentication failure |
| 101 | E_PEER_NOT_TRUSTED | yes | IK initiator static key unknown or revoked; sent by the responder after completing the handshake. Also the fatal ERROR that ends the sessions of a peer that was revoked, and the IPC answer to transfer.send for a peer that is not trusted |
| 110 | E_PAIRING_EXPIRED | local | Joiner could not reach an inviter accepting the code (TTL elapsed or code unknown); never sent, because an inviter no longer accepts XX after the TTL. Also reported to the inviter's frontend when its invitation ran out. From IPC minor 3 pairing.done may say why a relay did not lead to an inviter (ipc-v1.md §4.3) |
| 111 | E_PAIRING_CONSUMED | yes | Capability already used or cancelled. Locally also: another join of the same engine with the same URI recorded the code first |
| 112 | E_PAIRING_PROOF_INVALID | yes | cap_proof mismatch |
| 113 | E_PAIRING_COMMIT_MISMATCH | yes | Revealed n_R does not match sas_commit |
| 114 | E_SAS_REJECTED | yes | A user rejected the SAS |
| Transfer (200–299) | |||
| 200 | E_TRANSFER_NOT_FOUND | yes | Resume of an unknown transfer. Non-final, not persisted |
| 201 | E_TRANSFER_CONFLICT | yes | Known transfer_id with different metadata |
| 202 | E_TRANSFER_OFFSET_INVALID | yes | Gap, overlap, out-of-range data, premature FIN |
| 203 | E_TRANSFER_HASH_MISMATCH | yes | Final verification failed |
| 204 | E_SOURCE_CHANGED | yes | Sender detected a modified source file |
| 205 | E_CANCELLED | yes | User-initiated cancellation. Locally also a cancelled or replaced pairing invitation |
| 206 | E_TRANSFER_EXPIRED | yes | Pending offer or incomplete transfer expired |
| 207 | E_STREAM_SUPERSEDED | yes | Non-fatal ERROR closing an older stream when the same transfer is re-opened on a new one |
| Storage / policy (300–399) | |||
| 300 | E_INSUFFICIENT_SPACE | yes | Free-space check failed |
| 301 | E_QUOTA_EXCEEDED | yes | Per-peer quota or pending-transfer limit; in the browser engine also a full file pool. Non-final, not persisted; the sender re-offers later |
| 302 | E_STORAGE_FAILURE | yes | I/O error on the receiver. Locally also a failure to commit the joiner's used-code record before XX message 3 (protocol-v1.md §10.1), and also every refusal of a start because of the key store or state.db (a newer state.db is E_STATE_VERSION) and every other failure or refusal of a reset (the lock and an invalid config.toml have their own codes below) |
| 303 | E_POLICY_DENIED | yes | Acceptance policy or user rejected. Locally also (IPC): engine.shutdown on an embedded engine, pair.invite and pair.cancel where the pairing rules refuse them, settings.set of a setting fixed by a command-line option, clip.send while clipboard_sync is off, in the browser engine pair.join for a pairing URI whose relay origin the user neither entered nor confirmed (checked after the URI and the used-code checks, and it consumes no code), and in the browser engine in session mode relay.provision (refused before any request) |
| Local only (32768+) | |||
| 32768 | E_STATE_LOCKED | local | Another engine instance owns the state directory. The desktop app does not treat it as a failure when the owner is a daemon of the same user: it attaches. Also the answer of a reset while an engine holds the lock |
| 32769 | E_ENGINE_UNAVAILABLE | local | CLI cannot reach or start an engine |
| 32770 | E_IPC_VERSION | local | CLI and engine IPC versions incompatible |
| 32771 | E_IPC_UNKNOWN_METHOD | local | IPC method ID not known to the engine |
| 32772 | E_IPC_INVALID_PARAMS | local | IPC params do not match the method schema |
| 32773 | E_NOT_FOUND | local | Peer, pairing handle, transfer or (browser engine) source token referenced via IPC does not exist |
| 32774 | E_STATE_VERSION | local | state.db schema is newer than the engine supports; in the browser engine also a key record of a newer format than the build understands. Never answered with an offer to reset: the data is intact and a newer build reads it |
| 32775 | E_CONFIG_INVALID | local | config.toml cannot be read: not valid TOML, a key that the engine does not know, a value of the wrong type or outside its range, or a secret-like key. The start is refused; the message names the file and the key, never the value. It is a start-up error of the process that tried to start the engine (CLI, daemon, desktop app) or to select the key store for a reset and does not occur in an IPC answer |
All TRANSFER_CANCEL reasons are final for the transfer_id except E_TRANSFER_NOT_FOUND and E_QUOTA_EXCEEDED. Pausing, including pauses caused by temporary conditions such as a full disk, uses TRANSFER_PAUSE, not a cancel code.
Unknown codes received from a peer MUST be treated as generic failures of their range (e.g. an unknown 2xx code as a failed transfer) and MUST NOT cause a protocol error.