-
Notifications
You must be signed in to change notification settings - Fork 138
Description
As identified in #1040, the spec has an over reliance on AbortError...
The Payment Request specification uses AbortError inconsistently across different failure scenarios, conflating:
- User-initiated cancellation
- Developer errors (API misuse)
- Security/policy violations
- System/infrastructure failures
This makes it impossible for merchants to programmatically distinguish between these fundamentally different error categories.
Error Categories (Web Platform Conventions)
| Category | Appropriate Exception | Semantics |
|---|---|---|
| Developer error | InvalidStateError, NotAllowedError |
API called incorrectly; caller's fault |
| User action | AbortError |
User explicitly cancelled |
| Security/policy | SecurityError, NotAllowedError |
Permission denied, policy violation |
| System/infra | OperationError |
External system failure (handler crash, OS kill) |
Problematic Cases in show()
1. Document Not Visible
Location: show() method, step 6
Current behavior:
If document's visibility state is not "visible", return a promise
rejected with an "AbortError" DOMException.
Problem: This is a developer error — the page called show() while not visible (e.g., background tab). The user didn't abort anything.
Should be: NotAllowedError
2. Payment Request Already Showing
Location: show() method, step 8
Current behavior:
If the user agent's payment request is showing boolean is true, then:
- Set request.[[state]] to "closed"
- Return a promise rejected with an "AbortError" DOMException.
Problem: This is a developer error — calling show() when a payment UI is already visible. The user didn't abort anything.
Should be: InvalidStateError
Rationale:
- This is classic "object in invalid state" per WebIDL
- Similar to calling
start()on an already-started operation - Consistent with step 7 which uses
InvalidStateErrorfor wrong[[state]]
3. UA Immediate Abort (Private Browsing)
Location: show() method, step 12
Current behavior:
Optionally:
- Reject acceptPromise with an "AbortError" DOMException.
- [Note: allows UA to act as if user immediately aborted]
Problem: This conflates UA policy decisions with user cancellation. In private browsing mode, the user agent is refusing, not the user.
Should be: NotAllowedError
Rationale:
- Private browsing = UA policy to protect privacy =
NotAllowedError
4. detailsPromise Rejection
Location: Update algorithm
Current behavior:
Upon rejection of detailsPromise:
- Abort the update with request and an "AbortError" DOMException.
Problem: If the merchant's detailsPromise rejects, that's a developer error (their server failed, their code threw). Using AbortError implies the user cancelled.
Should be: Pass through the original rejection reason, or use OperationError
Rationale:
- The merchant's own promise failed; that's not "abort".
- Original exception provides better debugging
Problematic Cases in retry()
5. Document Becomes Inactive During Retry
Location: retry() method
Current behavior:
If document stops being fully active while the user interface is being shown:
- Close down the user interface
- [No explicit rejection specified, but likely AbortError]
Problem: Document deactivation during retry is an infrastructure failure, not user cancellation.
Should be: InvalidStateError
Proposed Fix Summary
| Case | Current | Proposed | Priority |
|---|---|---|---|
| Document not visible | AbortError |
InvalidStateError |
High |
| Already showing | AbortError |
InvalidStateError |
High |
| Private browsing abort | AbortError |
NotAllowedError |
Medium |
| detailsPromise rejects | AbortError |
Original error / OperationError |
High |
| Payment handler error | AbortError |
OperationError |
High |
Backwards Compatibility
Changing error types is technically breaking, but:
- Most merchants catch all errors from
show()generically - Those parsing error messages are already dealing with inconsistency
- Semantic correctness enables better error handling going forward
- Can be staged: update spec, then implementations, with clear release notes