> For the complete documentation index, see [llms.txt](https://docs.reya.xyz/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.reya.xyz/developers/connectivity/handling-ambiguous-outcomes.md).

# Handling ambiguous outcomes

This describes the API 3.6.2 transport-outcome contract. Before API 3.6.0, `UNAVAILABLE_MATCHING_ENGINE_ERROR` may also mean an unknown outcome; treat it conservatively and reconcile first.

A connection failure does not tell you whether an operation succeeded. An order may have been accepted before its reply was lost. Sending a replacement immediately can create a second order or duplicate exposure.

## Choose the action from the error code

The same contract applies to `createOrder`, `modifyOrder`, `cancelOrder`, `cancelAll`, and `cancelAllAfter`, over REST and WebSocket.

| Error                         | What it means                                                             | What to do                                                                                                                               |
| ----------------------------- | ------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| `SERVICE_UNAVAILABLE_ERROR`   | The service was temporarily unavailable. The request was not accepted.    | Re-sign with a fresh nonce and resubmit, keeping the same `clientOrderId` when supplied. Back off while the service remains unavailable. |
| `ORDER_OUTCOME_UNKNOWN_ERROR` | The operation's outcome could not be confirmed. It may have been applied. | Reconcile order state and executions before resubmitting. Never replace an unresolved attempt with a fresh nonce.                        |

Branch on `error`, not `message`. REST continues to return HTTP 400 for these errors; that status alone does not prove the operation was rejected. If the client receives no response at all, treat the outcome as unknown too.

## Check what happened

Keep the complete original signed request for reconciliation.

1. Read `GET /v2/wallet/{address}/openOrders` and match within the original account and market using the submitted order identifiers. Compare the operation's requested state with the observed state.
2. Inspect order updates, terminal events, and recent [executions](/developers/executions-and-settlement/executions-and-trade-history.md). An order can fill immediately and never appear in the current open-orders list. Execution records correlate through order IDs and fill IDs, not the request nonce; do not assume execution history supports a clientOrderId lookup.
3. Keep the attempt unresolved if evidence is missing, delayed, or ambiguous. An empty lookup is not proof of failure: an order may have filled rather than been cancelled.

Reconciliation has these limits:

* A lost immediate-fill reply can leave insufficient identifiers to identify the exact execution.
* Later modifications can obscure the original outcome.
* Current open orders cannot reconstruct a `cancelAll` request's original `cancelledCount`.
* Open orders cannot establish whether `cancelAllAfter` armed, refreshed, or disarmed a timer. Another refresh changes the deadline.
* `clientOrderId` is not permanent deduplication: a closed order may no longer reserve its ID. See [Order lifecycle](/developers/order-entry/order-lifecycle.md).

## Why a fresh nonce matters

Nonces must increase for each signer across all markets and operations, so a later accepted request can invalidate the nonce of an earlier unsent request. `INVALID_NONCE_ERROR` therefore does not establish whether that earlier request succeeded. See [Signatures & Nonces](/developers/authentication/signatures-and-nonces.md).
