# Stuck transactions: RBF and CPFP

A UTXO transaction can sit unconfirmed because its fee rate is too low for the current mempool. There are two fixes: **replace it** with a higher-fee version (RBF), or **pull it through** with a child that pays a high fee (CPFP). RBF works on Bitcoin and Litecoin; CPFP works on every UTXO chain.

## Before you start

- The txid and chain of the stuck transaction, and the key that signed it.
- To use RBF the original must have signalled replaceability. `rbf` defaults to **true** in [Build](https://docs.rarebl.com/api/tx/build), so transactions you built signal it.
- Ethereum and TRON: v2 builds ETH transactions with the pending nonce and has no call to replace a pending transaction with the same nonce. Wait, or send again once it is confirmed or dropped.

## Step 1 — Find out what is going on

```bash cURL
curl "https://api.rarebl.com/open/tx/status?chain=btc&id=<txid>"
curl "https://api.rarebl.com/open/tx/outspends?chain=btc&id=<txid>"
curl "https://api.rarebl.com/open/fees/recommended?chain=btc"
```

```python Python
print(c.status("btc", txid))
print(c.outspends("btc", txid))
```

```bash Shell
rarebl status --chain btc <txid>
```

**You should see** `status: "pending"` with 0 confirmations. Then compare:

- The transaction's fee rate (`feeRate` in [Transaction](https://docs.rarebl.com/api/tx/get)) against the `fast` and `standard` rates from [Recommended fees](https://docs.rarebl.com/api/fees/recommended).
- [Output spend status](https://docs.rarebl.com/api/tx/outspends): whether its outputs are spent in the mempool, which matters for CPFP.
- A `tx.dropped` [webhook](https://docs.rarebl.com/guides/webhooks) fires when a transaction has been gone for 24 hours, and `tx.replaced` fires when it is replaced (with the new txid).

## Step 2 — Choose a fix

| Fix | Use when | Chains |
| --- | --- | --- |
| **RBF**: rebuild with the same inputs and a higher `feeRate` | You built the transaction and it signalled `rbf`. | BTC, LTC |
| **CPFP**: spend an unconfirmed output of the stuck transaction with a high fee | You own an output of it (usually your change), or RBF is not possible. | All UTXO chains |

## Step 3 — Replace it (RBF)

Build again with the **same inputs** and recipient and a **higher `feeRate`** (above the original, with room for the network's replacement rules). Spending a different set of inputs creates a second payment instead of a replacement.

```bash cURL
curl -X POST https://api.rarebl.com/open/tx/build -H "Content-Type: application/json" -d '{
  "chain": "btc",
  "inputs": [{"txid": "<same input txid>", "vout": 1}],
  "to": [{"address": "<same recipient>", "amount": "0.0015"}],
  "change": "<your change address>",
  "feeRate": "40",
  "rbf": true
}'
```

```python Python
build = c.build({"chain": "btc", "inputs": [{"txid": input_txid, "vout": 1}],
                 "to": [{"address": dest, "amount": "0.0015"}], "change": addr, "feeRate": "40", "rbf": True})
sigs = rarebl.sign_build(build, key, expect={"to": {"address": dest, "amount": "0.0015"}})   # verifies every digest first
c.assemble(build["unsigned"], sigs, broadcast=True)
```

`expect` is required when you sign, so name the same recipient and amount as the original payment; change may only return to your own input addresses. The default fee cap is 1000 sat/vB (BTC, LTC), so a replacement above that needs `maxFeeRate` in `expect`.

**You should see** a new `unsigned` and `toSign` with a higher `feeRate`. Verify, sign, assemble and broadcast as in [Send a transaction](https://docs.rarebl.com/guides/send-a-transaction); the new transaction replaces the old one in the mempool. A `tx.replaced` webhook, or [Transaction status](https://docs.rarebl.com/api/tx/status), tells you which txid won.

## Step 4 — Or pull it through (CPFP)

Spend an **unconfirmed output of the stuck transaction** in a new transaction with a high fee, so miners include both together. The change output of your own payment is the usual candidate.

1. Find the output (for example `n: 1`, your change) in [Transaction](https://docs.rarebl.com/api/tx/get) and confirm it is unspent with [Output spend status](https://docs.rarebl.com/api/tx/outspends).
2. Build with **exact `inputs`** pointing at that output and a higher `feeRate`, sending to an address you control:

```json
{
  "chain": "btc",
  "inputs": [{"txid": "<stuck txid>", "vout": 1}],
  "to": [{"address": "bc1q…your own address", "amount": "max"}],
  "feeRate": "60"
}
```

**You should see** a build with one input and no change. Sign it with `expect` set to your own address and `amount: "max"` (a `max` spend must leave no change output), then broadcast it. If the node does not accept the unconfirmed input, the build fails with `inputs_unknown` or `inputs_spent`.

## Step 5 — Choose the rate

The miner looks at the parent and the child **together**. To reach a target rate, the child's fee must cover its own size and the parent's shortfall: `child fee = target × (parent vsize + child vsize) − parent fee`. For example, a 141 vB parent that paid 705 sats (5 sat/vB) and a 110 vB child, aiming for 40 sat/vB overall, needs a child fee of `40 × 251 − 705 = 9,335` sats, about 85 sat/vB on the child. [Estimate](https://docs.rarebl.com/api/tx/estimate) gives you the child's size before you commit.

## Prevention

- Use `priority: "fast"` or a fixed `feeRate` from [Recommended fees](https://docs.rarebl.com/api/fees/recommended) for payouts that matter.
- Keep `rbf: true` (the default) on Bitcoin and Litecoin.
- Follow every payment with a `tx.confirmations` [webhook](https://docs.rarebl.com/guides/webhooks) so you notice stuck ones quickly.

## Common errors

| Reason | What it means | What to do |
| --- | --- | --- |
| `API422` `inputs_spent` | The input was already spent, maybe by the replacement or by the transaction itself. | Check [Output spend status](https://docs.rarebl.com/api/tx/outspends) and the new txid. |
| `API422` `inputs_unknown` | The node does not know that unconfirmed input. | Wait for the parent to propagate, or rebuild. |
| `API422` `node_rejected` | The node refused the replacement, for example `insufficient fee` or `min relay fee not met`. | Raise `feeRate`: a replacement must pay more than the original. |
| `API422` `fee_too_high` | The fee is above the safety limit. | Lower `feeRate`. |
| `API429` | Compute: 2 per second; write: 6 per minute. | Wait `Retry-After`. |

## Next steps

- [Send a transaction](https://docs.rarebl.com/guides/send-a-transaction): the verify, sign and broadcast steps.
- [Webhooks](https://docs.rarebl.com/guides/webhooks): `tx.confirmations`, `tx.dropped`, `tx.replaced`.
- [Errors and rate limits](https://docs.rarebl.com/guides/handle-errors).
