View Issue Details
| ID | Project | Category | View Status | Date Submitted | Last Update |
|---|---|---|---|---|---|
| 0011980 | Taler | wallet (iOS App) | public | 2026-11-09 12:40 | 2026-11-09 12:40 |
| Reporter | bot-cg [agent] | Assigned To | Resolution deadline | ||
| Implementer | Reviewer | ||||
| Release signed by | Deployed by | ||||
| Verifier | Communicator | CM_7 | |||
| Data protection authority notification required | No | ||||
| CSIRT notification required | No | ||||
| Estimated effort (hours) | Actual effort (hours) | 0 | |||
| Fast-track | No | ||||
| Work package | none | ||||
| Priority | normal | Severity | major | Reproducibility | always |
| Status | new | Resolution | open | ||
| Summary | 0011980: Authorize at Bank: a KYC-gated withdrawal reopened from its URI spins for ever -- wallet-core says why (7046, txState pending/kyc) and the app discards it with `try?` | ||||
| Description | A withdrawal that has gone into `pending/kyc` leaves "Authorize at Bank" spinning for ever, with no error, no explanation and no way forward -- while wallet-core has already said exactly what is wrong. The sequence ------------ 1. A bank-integrated withdrawal is started and reaches `pending/kyc` (the exchange wants a legitimization check). 2. The same `taler://withdraw/` URI is opened again -- the user taps the link in their banking app a second time, or the sheet is re-entered. 3. `WithdrawAcceptDone.viewDidLoad()` calls `acceptBankIntWithdrawal` unconditionally (`WithdrawAcceptDone.swift:29-45`). It is keyed on the URL and never asks whether a transaction for it already exists, or in what state. 4. wallet-core refuses, correctly: acceptBankIntegratedWithdrawal -> { "code": 7046, "hint": "Error (WALLET_REQUEST_TRANSACTION_STATE_UNSUPPORTED)", "message": "unable to confirm withdrawal in current state", "txState": { "major": "pending", "minor": "kyc" } } 5. The call site is `if let result = try? await ...`, so the error is discarded. `transactionId` stays nil. 6. `body` therefore takes its `else` branch (`:77-82`) and renders `LoadingView` -- a spinner -- with `.task { await viewDidLoad() }` attached to it, so it tries again and fails again. The user is left on a screen headed "Authorize at Bank" showing a spinner that will never resolve. The only control is Cancel. **The reason is in the error payload the app threw away**: `txState.minor == "kyc"`. How often --------- Not a one-off. Three occurrences in one episode of `c2h-9` (e00012) and again in `c2h-8` (e00008), across two separate two-hour campaign runs -- same fingerprint both times. It reproduces whenever a KYC-gated withdrawal URI is opened twice. Why it matters beyond this screen --------------------------------- This is the same defect as 11914 seen from a third angle, and the worst version of it so far: there the user had to drill three screens down to find out what was wanted of them; here they are shown a spinner that implies the app is working on it. A progress indicator for a state that will never progress is worse than a blank screen. Suggested fix ------------- Two parts, and the first is the important one: 1. **Stop discarding the error.** `try?` at `:31` turns a precise, actionable wallet-core verdict into nil. Catch it, and render the failure instead of a spinner. (Same anti-pattern as 11975, where `Result.orUndefined` dropped a typed error.) 2. **7046 with `txState.minor == "kyc"` is not really an error**: it means the withdrawal exists and needs legitimization. The right response is to show that transaction -- which already renders the "Open legitimization website" button -- rather than to report a failure. I have a patch for part 1 and will attach it once it is built; I would rather not attach an unbuilt one. Part 2 needs the transaction id, which the 7046 payload does not carry, so it needs either a lookup by URI or an addition to the error -- a design call rather than a patch. Found by the fuzzing harness; `runs/c2h-9/findings.json`, fingerprint `f8b681cdce3c`. | ||||
| Tags | No tags attached. | ||||
| Date Modified | Username | Field | Change |
|---|---|---|---|
| 2026-11-09 12:40 | bot-cg | New Issue |