# UltraSend Errors and Retries

> Handle UltraSend rejection, timeout, duplicate, balance, and service failure states without double-sending or rebuilding transactions.

Canonical: https://nolimitnodes.com/docs/api-reference/ultrasend/errors-retries

Retry decisions depend on whether the server returned a definite response or the network result was ambiguous.

| HTTP | Code | Charged | Action |
|---|---|---:|---|
| `400` | `INVALID_BASE64` or `INVALID_TRANSACTION` | No | Fix construction or encoding. Do not retry unchanged. |
| `401` | `INVALID_API_KEY` | No | Replace the credential. |
| `402` | `INSUFFICIENT_BALANCE` | No | Fund the account and retry if the blockhash is still valid. |
| `403` | `ACCOUNT_DISABLED` | No | Restore an eligible subscription or contact support. |
| `409` | `SUBMISSION_IN_PROGRESS` | No additional charge | Wait briefly and retry the exact same signed payload. |
| `503` | `BILLING_UNAVAILABLE` | No confirmed acceptance | Stop or retry with bounded backoff. |
| `503` | `AUDIT_UNAVAILABLE` | No confirmed acceptance | Stop or retry with bounded backoff. |
| `503` | `UPSTREAM_UNAVAILABLE` | Reversed if initially committed | Retry only while the original blockhash remains valid. |

## Ambiguous timeout rule

If the client times out before receiving an HTTP or QUIC receipt, the relay may already be processing the signature. Retry the **same serialized bytes**. Do not fetch a new blockhash, rebuild, or resign until the original transaction is known to have expired.

```text
serialize and sign once
        |
        v
submit exact bytes ---- definite rejection ----> fix or stop
        |
        +---------- accepted receipt ----------> confirm with RPC
        |
        +---------- ambiguous timeout ---------> retry exact bytes
```

UltraSend deduplicates by customer and transaction signature for a bounded window. Your application should also retain the signature and serialized payload until the send attempt reaches a terminal state.

## Backoff

Use short bounded backoff only for ambiguous transport errors, `409`, and recoverable `503` responses. A practical starting schedule is 100 ms, 250 ms, 500 ms, and 1 second, capped by the transaction blockhash lifetime and your own execution deadline.

Do not run an unbounded retry loop. When the blockhash expires, create and sign a new transaction as a new submission attempt.

## Billing outcomes

- Invalid or unauthorized: not charged.
- Insufficient balance: not charged.
- Duplicate or already in progress: no second charge.
- Forwarding failure: charge reversed.
- Accepted but never observed on-chain: charged.
- Accepted and finalized with a chain error: charged.

Return to the [complete implementation guide](/docs/api-reference/ultrasend/overview).
