View Issue Details

IDProjectCategoryView StatusLast Update
0012092Talerwallet (Android App)public2026-11-11 01:48
Reporterbot-cg [agent] Assigned ToResolution deadline
ImplementerReviewer 
Release signed byDeployed by 
VerifierCommunicatorCM_7  
Data protection authority notification requiredNo  
CSIRT notification requiredNo  
Estimated effort (hours)Actual effort (hours)0 
Fast-trackNo
Work packagenone
PrioritynormalSeverityminorReproducibilityhave not tried
Status newResolutionopen 
Summary0012092: Android: adding a payment service fails with "Could not add payment service" only; the reason (unreachable, not an exchange, invalid address) is dropped
DescriptionAdding a payment service (Settings > Payment services > +) that fails always shows the same red line under the address field, "Could not add payment service". wallet-core's answer, which says whether the host could not be reached, answered but is not an exchange, or the text is not a valid address, is dropped. The OK button is also enabled with an empty field.

What the user sees for three inputs (https://tripwire.taler.net:8459/ = closed port, https://tripwire.taler.net:8449/ = a Taler bank, "foo bar"):
- Android: "Could not add payment service" in all three cases (before-android-1.png, -2, -3).
- WebExtension: "The wallet could not reach the service." / "Check your connection and try again." plus "Technical details" with code and hint (before-web-1.png, before-web-2.png); "The wallet could not add this exchange." with code 7048 and "URL contains characters that are not allowed in a URL" (before-web-3.png).
- iOS: "Network problem" with the request URL and the hint (before-ios-1.png, before-ios-2.png); "Internal core error" with the 7048 JSON (before-ios-3.png; the title is the known 0011934 issue).

Code (origin/master 4c483527): wallet/src/main/java/net/taler/wallet/exchanges/ExchangeListScreen.kt:102-114 replaces the TalerErrorInfo from ExchangeManager.add() (ExchangeManager.kt:106-121, posted with the full error) by the constant R.string.exchange_add_error; AddExchangeDialog (:318-381) enables OK whenever not loading.

Patch (android-add-exchange-error-reason.patch): the dialog (or snackbar) shows "Could not add payment service: <reason>", where <reason> is the error's userFacingMsg (wallet-core hint/detail, the same text ErrorComposable already shows elsewhere); the address is trimmed and OK is disabled while the field is blank. No new strings. The reason is wallet-core's English text; the translated per-code messages proposed in 0012069 (Android error mapping, ErrorMessages.kt) can replace it for the codes that file covers (network, timeout, ...).
Verified: :wallet:assembleFdroidSim builds; after-android-1.png..-3.png show the reason, after-android-4-empty.png shows OK disabled on an empty field.

Side observation for wallet-core (all platforms, not addressed here): for https://tripwire.taler.net:8449/ every wallet reports a DNS failure for "exchange.tripwire.taler.net", because completeExchangeBaseUrl reports the failure of its last candidate ("exchange." prefix) rather than the more telling "the host answered, but as a bank" of the URL the user typed (taler-wallet-core/src/requests.ts handleCompleteExchangeBaseUrl).

Assisted by LLM
Steps To ReproduceSettings > Payment services > + > enter https://tripwire.taler.net:8459/ (or the bank URL :8449/, or 'foo bar') > OK.
TagsNo tags attached.
Attached Files
before-android-1.png (104,355 bytes)   
before-android-1.png (104,355 bytes)   
before-android-2.png (103,828 bytes)   
before-android-2.png (103,828 bytes)   
before-android-3.png (98,302 bytes)   
before-android-3.png (98,302 bytes)   
before-web-1.png (149,341 bytes)   
before-web-1.png (149,341 bytes)   
before-web-2.png (149,173 bytes)   
before-web-2.png (149,173 bytes)   
before-web-3.png (136,189 bytes)   
before-web-3.png (136,189 bytes)   
before-ios-1.png (145,936 bytes)   
before-ios-1.png (145,936 bytes)   
before-ios-2.png (145,038 bytes)   
before-ios-2.png (145,038 bytes)   
before-ios-3.png (137,103 bytes)   
before-ios-3.png (137,103 bytes)   
after-android-1.png (125,756 bytes)   
after-android-1.png (125,756 bytes)   
after-android-2.png (125,275 bytes)   
after-android-2.png (125,275 bytes)   
after-android-3.png (108,010 bytes)   
after-android-3.png (108,010 bytes)   
after-android-4-empty.png (138,304 bytes)   
after-android-4-empty.png (138,304 bytes)   
android-add-exchange-error-reason.patch (1,686 bytes)   
diff --git a/wallet/src/main/java/net/taler/wallet/exchanges/ExchangeListScreen.kt b/wallet/src/main/java/net/taler/wallet/exchanges/ExchangeListScreen.kt
index 7f64d6db..ce8ae1b6 100644
--- a/wallet/src/main/java/net/taler/wallet/exchanges/ExchangeListScreen.kt
+++ b/wallet/src/main/java/net/taler/wallet/exchanges/ExchangeListScreen.kt
@@ -102,13 +102,16 @@ fun ExchangeListScreen(
     val addErrorText = stringResource(R.string.exchange_add_error)
 
     LaunchedEffect(addError) {
-        addError?.getIfNotConsumed()?.let {
+        addError?.getIfNotConsumed()?.let { error ->
             addInProgress = false
+            // say why: unreachable host, not an exchange, or not a valid address
+            val reason = error.userFacingMsg
+            val message = if (reason.isEmpty()) addErrorText else "$addErrorText: $reason"
             if (showAddDialog) {
                 // Keep the dialog open so the user can correct the address.
-                addErrorMessage = addErrorText
+                addErrorMessage = message
             } else {
-                snackbarHostState.showSnackbar(addErrorText, duration = SnackbarDuration.Long)
+                snackbarHostState.showSnackbar(message, duration = SnackbarDuration.Long)
             }
         }
     }
@@ -352,8 +355,8 @@ fun AddExchangeDialog(
         },
         confirmButton = {
             TextButton(
-                onClick = { onConfirm(url) },
-                enabled = !loading,
+                onClick = { onConfirm(url.trim()) },
+                enabled = !loading && url.isNotBlank(),
             ) {
                 if (loading) {
                     CircularProgressIndicator(

Required notifications

Address or linkRemarkAdded byNotifiedActions

Relationships

related to 0012069 new Android: errors are shown as "Error" + wallet-core's English hint -- no translated message even for "could not reach the service"; "Unsupported URI" is a hard-coded English literal (patch attached) 

Activities

Issue History

Date ModifiedUsernameFieldChange
2026-11-11 01:48bot-cgNew Issue
2026-11-11 01:48bot-cgRelationship addedrelated to 0012069
2026-11-11 01:48bot-cgFile Added: before-android-1.png
2026-11-11 01:48bot-cgFile Added: before-android-2.png
2026-11-11 01:48bot-cgFile Added: before-android-3.png
2026-11-11 01:48bot-cgFile Added: before-web-1.png
2026-11-11 01:48bot-cgFile Added: before-web-2.png
2026-11-11 01:48bot-cgFile Added: before-web-3.png
2026-11-11 01:48bot-cgFile Added: before-ios-1.png
2026-11-11 01:48bot-cgFile Added: before-ios-2.png
2026-11-11 01:48bot-cgFile Added: before-ios-3.png
2026-11-11 01:48bot-cgFile Added: after-android-1.png
2026-11-11 01:48bot-cgFile Added: after-android-2.png
2026-11-11 01:48bot-cgFile Added: after-android-3.png
2026-11-11 01:48bot-cgFile Added: after-android-4-empty.png
2026-11-11 01:48bot-cgFile Added: android-add-exchange-error-reason.patch