Skip to content
bitcoinsv.design

Search the guide

Search the guide

Errors and failed payments

The model for every failure in a BSV product: plain words first, whether money moved, what to do next, and the code underneath for support.

When something fails, the person needs to know whether they lost money. We recommend one model for every failure, in four parts and in this order: what happened, in plain words; whether any money moved; what the user can do next; and, underneath, the code support will ask for.

Whether money moved is the part an error message must never leave out. Most failed payments fail before anything leaves the wallet. When that is true, say so.

Sending, in the daily spending wallet, covers the errors on a send screen in detail. This page is the general model, for apps, wallets and agents alike.

The four parts

What happened. One sentence, about the user's situation rather than the system's: "Anna's couldn't be looked up", not "Lookup failed".

Whether money moved. "Nothing was sent", "Nothing left your wallet for this", or, rarely, "This payment went through, but the receipt didn't arrive". If you do not know yet, say that, and say when you will.

What to do next. One action, as a button where there is one: add money, try again, choose another way to pay, ask for help.

The code. Kept for support, out of the way.

Do

Say whether money moved in every message that follows a payment attempt, including when the answer is that nothing left the wallet.

Do

End every error with one thing the user can do, as a button where there is one.

Do

Put the error code and technical detail in an expandable details area with a copy button, so support can ask for it.

Do

Keep what the user entered. Return them to where they were with the amount, recipient and note still filled in.

Don't

Write "Something went wrong" on its own. If you truly do not know what happened, say what you do know and whether money moved.

Who is speaking

A wallet and an app both see a failure, and only one of them should explain it. When the user refused something in their wallet, the wallet already knows, and the app only receives a rejection. When the network rejects a payment, the wallet has the detail and the app has the context.

Do

Explain a failure in the app when it is about the app's task, such as an article not unlocking, and in the wallet when it is about the user's money or permissions.

Retrying

Some failures are worth retrying, and some are dangerous to retry. The wallet library reports a broadcast it could not complete as a service error, and keeps it queued to try again. A second payment on top of a queued one can pay twice.

Don't

Offer "Try again" on a payment until you know the first attempt did not go out.

Do

Tell the user once when their wallet is retrying for them: "Your wallet will keep trying to send this. You don't need to pay again."

The failures

What happenedSignal underneathWhat to sayWhat to do next
The user cancelled in their walletThe wallet call is rejected as denied"You cancelled the payment. Nothing was sent."Back to the review screen, everything filled in
Not enough moneyWERR_INSUFFICIENT_FUNDS; the shortfall is moreSatoshisNeeded"You need 1,200 more sats."Add money, or lower the amount
A conflicting payment was seen firstWERR_REVIEW_ACTIONS, a result with status doubleSpend"This payment didn't go through. Nothing left your wallet for it."Check recent activity
Rejected by the networkA result with status invalidTx"The network didn't accept this payment. Nothing was sent."Try again once, since nothing went out; then contact support with the code
The network could not be reachedA result with status serviceError, or the app's own request fails"Your wallet couldn't reach the network. It will keep trying."Wait; do not pay again
The handle does not resolveThe lookup failsWhich part failed: no such handle, the handle's domain is unreachable, or its certificate did not check outCheck the spelling, or ask the recipient
The recipient cannot take a Only a plain address is offered"Anna's handle only accepts a plain address. The payment can still go, without her wallet confirming it."Continue, or choose another way
A permission was refusedPermission denied (BRC-116)"Pixel Arcade can't save your progress without this."Ask again when they next use the feature
A permission was revokedThe wallet asks the user again on the next call"The Vision needs your permission again."Explain the prompt that is about to appear
An allowance is used upThe month's limit is reached"You've used this month's 5,000 sats for The Satoshi Vision. It resets on 1 December."Approve this one, raise the limit, or wait
An reached its budgetThe wallet holding the agent's funds refuses"Example Assistant has spent its 5,000 sats budget and has stopped."Tell the owner; they top up or end the task
No wallet connectedThe app has not connected, or the user is not signed in"Connect your wallet to read this article."Connect wallet
No wallet installedThe wallet library finds no wallet to talk to"To pay here you need a BSV wallet."Help them install one, and keep the rest of the app usable
Opened in an ordinary phone browserA phone browser cannot reach a wallet at all"To pay here, open this page in your BSV wallet's browser."Copy link, and help them install a wallet

The amounts and names in this table are examples. Show the real shortfall, the real limit and the real date.

Sending has the detail for a send screen: cancelling, not enough money, conflicts, rejection, handles and plain-address recipients. Legacy compatibility explains the recipient that only takes a plain address, and Paying by handle explains handles.

Money sent to an address on another network is a different kind of failure, because it does not fail at all. See Wrong-network payments.

Failures that are not errors

Two states look like failures and are not.

Waiting for the user. A request waiting on a wallet prompt can take minutes. The prompt liveness standard (BRC-219) says the app waits rather than timing it out. Show "Waiting for your wallet…", not an error.

A refusal. The permissions standard (BRC-116) says apps should treat a denied permission as an expected answer. It needs a sentence about what the app cannot do, not a red banner.

Don't

Show a refusal or an unanswered wallet prompt in an error style. Both are the user's choice, and red tells them they did something wrong.

When many payments fail

For an app charging many small amounts, one failure in a hundred is a rate, not an event. Charging per use covers deciding what happens then and telling the user once. The same applies to an agent, and the owner is the person to tell. See Letting an agent spend.

Open questions

  • When a payment's outcome is unknown for a while, how long can a product say "We're checking" before people pay again?
  • Should an app or the wallet explain a used-up allowance? Both see it, and the standard does not say which.
  • Do people read "Nothing was sent" as reassurance, or does any failure message make them check their balance anyway?

Written from: BRC-100, BRC-116 §7.5 and §7.6, BRC-219, @bsv/sdk 4.0 wallet errors (WERR_INSUFFICIENT_FUNDS, WERR_REVIEW_ACTIONS, ReviewActionResultStatus), Sending, Letting an agent spend.

Checklist

The rules on this page, in a form you can work through.

9 rules