What happened
The payment rail was not available when the transaction was attempted. No funds were moved. The transaction is in a terminal failed state withfailureCode: rail_unavailable.
This is not a problem with the format of your request or the recipient’s details. Two different situations return this code, and the code alone does not separate them: a passing outage on a rail Conduit does serve, which a retry clears, and a corridor Conduit does not serve, which no retry clears. Retry a few times; if the code keeps coming back, treat the corridor as unsupported and contact support.
Common causes
- Scheduled maintenance — the rail or its underlying network is in a maintenance window
- Transient outage — the rail experienced an unexpected interruption
- All routing options exhausted — every configured provider for this corridor was unavailable simultaneously
- Corridor not served — Conduit has no route for this currency and rail combination yet
A rail that can never settle the payout’s currency —
fedwire on a EUR
balance, sepa on a USD one — no longer reaches this state. It is refused at
create with 422 PAYOUT_RAIL_CURRENCY_MISMATCH.Recovery
Retry this terminal state a bounded number of times. Submit a new transaction
with exponential backoff starting at 30 seconds, and cap the attempts: one of
the two causes never clears. The original transaction cannot be resumed.
Idempotency-Key for each new attempt.
3. Contact support if the outage persists
If the rail is consistently unavailable after multiple retries over 30+ minutes, contact support with:
- The
instancevalue from the error response - The rail and corridor you are requesting
- The correlation IDs from the failed attempts
Prevention
- Implement retry logic with backoff — wrap payout requests in a retry loop with exponential backoff (30s, 60s, 120s) and a cap of 3-5 attempts
- Handle
transaction.failedwith this code — branch onfailureCode === 'rail_unavailable'to retry a bounded number of times, then surface a failure; the code does not tell you whether the cause clears, so do not retry without a cap - Consider alternative rails — if your integration supports multiple rails for a corridor, route around the unavailable one on retry
Related webhooks
Thetransaction.failed event fires when the rail is unreachable:
Related endpoints
- GET /v2/transactions/:id — read transaction state
- POST /v2/payouts — submit a new payout