v149 · Web APIs · Payment Request
Error Taxonomy
Complete reference for every outcome a payment handler can signal, with interactive code samples showing how each error reaches the merchant page and what the correct response is for each case.
outcome taxonomy
| Handler action | Merchant sees | User intent? | Recommended response |
|---|---|---|---|
| Resolve with payment details | response.complete('success') |
✓ paid | Confirm order, send email, redirect to receipt |
| User presses Cancel / closes sheet | err.name === 'AbortError' |
deliberate cancel | Return to cart; do NOT retry automatically |
Handler throws OperationError |
err.name === 'OperationError' |
internal failure | Log error, offer retry or fallback method |
| Handler times out / crashes | Generic Error or AbortError |
unknown | Treat as OperationError; offer retry |
error flow (Chrome 149)
①
Payment Handler SW
Encounters an internal error (card expired, 3DS failed, network timeout…)
②
Payment Handler SW
Includes a human-readable message in the error
event.respondWith(Promise.reject(new DOMException('Card expired', 'OperationError')))Includes a human-readable message in the error
③
Browser
Propagates the structured error across the payment handler boundary (Chrome 149)
④
Merchant Page
Merchant reads
request.show() rejects with { name: 'OperationError', message: 'Card expired' }Merchant reads
err.message to surface a specific error to the user
interactive test harness
Run a payment handler outcome and see what the merchant catch block receives:
Install the handler before running a scenario.
// Select a scenario above…
handler-side code
// In the Payment Handler Service Worker
self.addEventListener('paymentrequest', event => {
event.respondWith(handlePayment(event));
});
async function handlePayment(event) {
try {
const result = await processCard(event.total);
return result; // → merchant sees 'success'
} catch (err) {
if (err.code === 'CARD_EXPIRED') {
// Chrome 149: throw OperationError with message
throw new DOMException('Card on file is expired', 'OperationError');
}
if (err.code === 'USER_CANCELLED') {
throw new DOMException('User cancelled', 'AbortError');
}
throw new DOMException(err.message, 'OperationError');
}
}
see also
- Error Reporting Demo — specific error scenarios
- Handler Integration — full SW + merchant code
- Feature index
implementation reference
Need the exact API surface, compatibility boundaries, errors, lifecycle, and source links? Read the matching gendn reference ↗