> ## Documentation Index
> Fetch the complete documentation index at: https://docs.orbit.devotel.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Troubleshoot number purchase failures: inventory races and provisioning retries

> Resolve the two hard checkout failures on number purchase — 409 NUMBER_NO_LONGER_AVAILABLE (someone else claimed the DID, or your own recently-released number is still in quarantine) and 502 NUMBER_PROVISIONING_FAILED (post-checkout provisioning step rolled back and refunded).

# Troubleshoot number purchase failures

Two response codes cover the purchase-step failures that aren't rejected up front by the
wallet, compliance, or sender-resolution gates:

* **`409 NUMBER_NO_LONGER_AVAILABLE`** — the DID you picked could not be claimed. Either
  another account bought it between your inventory search and checkout, or the response
  flags your own recently-released number still inside the carrier quarantine window.
* **`502 NUMBER_PROVISIONING_FAILED`** — the carrier order succeeded and the wallet was
  charged, but the platform-side step that registers the DID for inbound routing failed.
  Orbit rolls the purchase back: the charge is refunded to your wallet and the DID is
  released back to the carrier in the background.

Both are retryable, and both tell you nothing was left half-billed. Work the branch that
matches your code, then the checklist below.

<Note>
  Checkout rejections that stop before a carrier order — `402 INSUFFICIENT_BALANCE`, a
  `422` compliance-profile gate, or a sender-resolution conflict — are covered in the
  [Buy and provision numbers](/guides/buy-numbers) guide and the
  [insufficient-balance runbook](/troubleshooting/insufficient-balance). This page covers
  failures that happen at or after the carrier order.
</Note>

## Cause table

| Code                                                                            | What happened                                                                                                                                        | Recover by                                                                                      |
| ------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------- |
| `409 NUMBER_NO_LONGER_AVAILABLE`                                                | Inventory race: the DID visible at search-time was claimed by another account before your checkout reached the carrier                               | Re-run [inventory search](/guides/buy-numbers#2-search-inventory-first) and pick a fresh number |
| `409 NUMBER_NO_LONGER_AVAILABLE` with `details.recently_released_by_self: true` | Your own account released this DID recently; the carrier holds released numbers in a \~30-day quarantine before they re-enter the public pool        | Pick a different number — this one cannot be repurchased until the quarantine clears            |
| `502 NUMBER_PROVISIONING_FAILED`                                                | The purchase succeeded upstream, then the inbound-routing registration failed; the wallet was refunded and the DID released as a compensating action | Wait a moment and retry the checkout — the refund posts before your next attempt                |

A bulk purchase surfaces the same codes per row in the `failed[]` array instead of
failing the request: inspect each row's `error.code`, and remember the batch returns
`200` even when every row failed — gate on `succeeded.length`, not the status code.

## Decision checklist

1. **Re-run the preflight.** `GET /api/v1/numbers/available` returns live inventory — a
   row you saw minutes ago is not a reservation. Re-search, then forward the row's `id`
   into the purchase call so checkout targets a still-listed DID. A `409` on a fresh
   search result means the race repeated; pick another row.
2. **Retry only the failed bulk rows.** Failed rows in `failed[]` are never charged —
   `debited_cents` counts only `succeeded` — so re-submitting exactly the failed E.164s
   in a new `POST /numbers/buy-bulk` call is billing-safe. Do not replay the whole batch.
3. **Capture the request id.** If the failure recurs, keep `meta.request_id` from the
   error response (not a wildcard pattern — the exact `req_…` value). Wildcard or partial
   ids are rejected when you query logs or open a ticket; the full string is the handle.
4. **Recheck the ledger on a 502.** After `NUMBER_PROVISIONING_FAILED`, the Billing
   ledger shows the refund of the rolled-back charge before you retry, so the next
   purchase attempt draws against restored balance. If a 502 follows a cheaper "already
   charged" assumption, your retry is safe either way — the response only ever debits a
   succeeded purchase once.

## What not to do

* **Do not blind-duplicate the checkout request.** Re-issuing the identical purchase
  body against a stale search result re-runs the same losing race. Re-search first, then
  resubmit. For bulk purchases, replaying the whole batch re-attempts rows that already
  succeeded — always strip `succeeded` items first.
* **Do not treat a 409 as "try the same number harder".** The number is gone. Retrying
  the exact E.164 without a fresh search hit just repeats the rejection.
* **Do not double-buy after a 502.** A `NUMBER_PROVISIONING_FAILED` response has already
  refunded the debit — you are not paying twice by retrying, but you are not owed the
  number either; the compensating release sends it back to the carrier.

## When to escalate

Open a support ticket when the same DID keeps failing across a fresh search and a clean
retry, or when a 502 recurs on more than one purchase attempt within a few minutes —
that pattern points at a platform-side provisioning step that needs operator attention,
not a client-side fix. Include:

* The **exact `meta.request_id`** of one failed call (single and bulk responses both
  carry one; bulk failures also have a pollable `order_id` — bring that too).
* The E.164 and country of the number, and the error code you received.
* For `recently_released_by_self` 409s, whether you expect the \~30-day quarantine to
  have expired already.

## See also

* [Buy and provision numbers](/guides/buy-numbers) — the full search → buy → audit → wire
  checkout loop, including the bulk `failed[]` contract
* [Number lifecycle](/numbers/lifecycle) — release, reclaim, quarantine, and renewal
  states a purchased number moves through
* [Regulatory Preview](/numbers/regulatory-preview) — the `422` compliance gates that
  reject *before* the carrier order
* [Troubleshoot INSUFFICIENT\_BALANCE](/troubleshooting/insufficient-balance) — wallet
  pre-flight 402s
* [Error codes reference](/reference/error-codes) — full code catalogue
