fix: only throw on deserialize if kDebugMode is true (#2976)
What changed, and why it matters
This commit changes several parts of the Cake Wallet app so that, in normal use, unexpected stored values no longer crash the app. Instead, the app falls back to a safe default (usually 'medium' priority or 'descending' order). In debug builds, it still throws an error so developers can spot problems. The change is a defensive hardening fix: it reduces the chance that a corrupted or mismatched saved setting makes the wallet unusable, but it also means a bad value is silently accepted in production.
Treat as a reliability/defensive-fix commit. Review whether the fallback defaults are safe for fee estimation and transaction construction. Consider adding non-fatal error logging or telemetry in the release fallback path so corrupted persisted values are still detected. No immediate exploit response is indicated.
Security signals we found
Defensive fallback added for deserialization failures
Production crash converted to silent default-value behavior
Multiple coin modules and a UI ordering entity affected
No input validation or logging added for the fallback path
Issue #2972 referenced but not described in the commit
Evidence from the diff
The patch wraps default branches of deserialize() switch statements across transaction-priority classes (Bitcoin, Litecoin, Bitcoin Cash, Monero, Decred, Dogecoin, EVM chains) and ListOrderMode with if (kDebugMode). In release builds, instead of throwing an Exception, the code now returns a predefined default value. This prevents crashes from unhandled enum-like deserialization failures in production, at the cost of silently masking data integrity issues.
Changed components
cw_bitcoin/lib/bitcoin_transaction_priority.dartcw_core/lib/monero_transaction_priority.dartcw_decred/lib/transaction_priority.dartcw_dogecoin/lib/src/dogecoin_transaction_priority.dartcw_evm/lib/evm_chain_transaction_priority.dartlib/entities/list_order_mode.dartInspect captured patch +38 / −8
diff --git a/cw_bitcoin/lib/bitcoin_transaction_priority.dart b/cw_bitcoin/lib/bitcoin_transaction_priority.dart
index d1f45a54..d93070a7 100644
--- a/cw_bitcoin/lib/bitcoin_transaction_priority.dart
+++ b/cw_bitcoin/lib/bitcoin_transaction_priority.dart
@@ -1,4 +1,5 @@
import 'package:cw_core/transaction_priority.dart';
+import 'package:flutter/foundation.dart';
class BitcoinTransactionPriority extends TransactionPriority {
const BitcoinTransactionPriority({required String title, required int raw})
@@ -25,7 +26,10 @@ class BitcoinTransactionPriority extends TransactionPriority {
case 3:
return custom;
default:
- throw Exception('Unexpected token: $raw for BitcoinTransactionPriority deserialize');
+ if (kDebugMode) {
+ throw Exception('Unexpected token: $raw for BitcoinTransactionPriority deserialize');
+ }
+ return medium;
}
}
@@ -82,7 +86,10 @@ class LitecoinTransactionPriority extends BitcoinTransactionPriority {
case 2:
return fast;
default:
- throw Exception('Unexpected token: $raw for LitecoinTransactionPriority deserialize');
+ if (kDebugMode) {
+ throw Exception('Unexpected token: $raw for LitecoinTransactionPriority deserialize');
+ }
+ return medium;
}
}
@@ -132,7 +139,10 @@ class BitcoinCashTransactionPriority extends BitcoinTransactionPriority {
case 2:
return fast;
default:
- throw Exception('Unexpected token: $raw for BitcoinCashTransactionPriority deserialize');
+ if (kDebugMode) {
+ throw Exception('Unexpected token: $raw for BitcoinCashTransactionPriority deserialize');
+ }
+ return medium;
}
}
diff --git a/cw_core/lib/monero_transaction_priority.dart b/cw_core/lib/monero_transaction_priority.dart
index 81058f33..cc14b850 100644
--- a/cw_core/lib/monero_transaction_priority.dart
+++ b/cw_core/lib/monero_transaction_priority.dart
@@ -1,4 +1,5 @@
import 'package:cw_core/transaction_priority.dart';
+import 'package:flutter/foundation.dart';
class MoneroTransactionPriority extends TransactionPriority {
const MoneroTransactionPriority({required String title, required int raw})
@@ -30,7 +31,10 @@ class MoneroTransactionPriority extends TransactionPriority {
case 4:
return fastest;
default:
- throw Exception('Unexpected token: $raw for MoneroTransactionPriority deserialize');
+ if (kDebugMode) {
+ throw Exception('Unexpected token: $raw for MoneroTransactionPriority deserialize');
+ }
+ return medium;
}
}
diff --git a/cw_decred/lib/transaction_priority.dart b/cw_decred/lib/transaction_priority.dart
index 80a9c7e3..735d0b47 100644
--- a/cw_decred/lib/transaction_priority.dart
+++ b/cw_decred/lib/transaction_priority.dart
@@ -1,4 +1,5 @@
import 'package:cw_core/transaction_priority.dart';
+import 'package:flutter/foundation.dart';
class DecredTransactionPriority extends TransactionPriority {
const DecredTransactionPriority({required String title, required int raw})
@@ -19,7 +20,10 @@ class DecredTransactionPriority extends TransactionPriority {
case 2:
return fast;
default:
- throw Exception('Unexpected token: $raw for DecredTransactionPriority deserialize');
+ if (kDebugMode) {
+ throw Exception('Unexpected token: $raw for DecredTransactionPriority deserialize');
+ }
+ return medium;
}
}
diff --git a/cw_dogecoin/lib/src/dogecoin_transaction_priority.dart b/cw_dogecoin/lib/src/dogecoin_transaction_priority.dart
index b692cc57..ed12b87a 100644
--- a/cw_dogecoin/lib/src/dogecoin_transaction_priority.dart
+++ b/cw_dogecoin/lib/src/dogecoin_transaction_priority.dart
@@ -1,4 +1,5 @@
import 'package:cw_bitcoin/bitcoin_transaction_priority.dart';
+import 'package:flutter/foundation.dart';
class DogecoinTransactionPriority extends BitcoinTransactionPriority {
const DogecoinTransactionPriority({required String title, required int raw})
@@ -21,7 +22,10 @@ class DogecoinTransactionPriority extends BitcoinTransactionPriority {
case 2:
return fast;
default:
- throw Exception('Unexpected token: $raw for DogecoinTransactionPriority deserialize');
+ if (kDebugMode) {
+ throw Exception('Unexpected token: $raw for DogecoinTransactionPriority deserialize');
+ }
+ return medium;
}
}
diff --git a/cw_evm/lib/evm_chain_transaction_priority.dart b/cw_evm/lib/evm_chain_transaction_priority.dart
index b4ce5549..721c7e47 100644
--- a/cw_evm/lib/evm_chain_transaction_priority.dart
+++ b/cw_evm/lib/evm_chain_transaction_priority.dart
@@ -1,4 +1,5 @@
import 'package:cw_core/transaction_priority.dart';
+import 'package:flutter/foundation.dart';
class EVMChainTransactionPriority extends TransactionPriority {
final int tip;
@@ -23,7 +24,10 @@ class EVMChainTransactionPriority extends TransactionPriority {
case 2:
return fast;
default:
- throw Exception('Unexpected token: $raw for EVMChainTransactionPriority deserialize');
+ if (kDebugMode) {
+ throw Exception('Unexpected token: $raw for EVMChainTransactionPriority deserialize');
+ }
+ return medium;
}
}
diff --git a/lib/entities/list_order_mode.dart b/lib/entities/list_order_mode.dart
index b9eae682..e89f9ef7 100644
--- a/lib/entities/list_order_mode.dart
+++ b/lib/entities/list_order_mode.dart
@@ -1,5 +1,6 @@
import 'package:cake_wallet/generated/i18n.dart';
import 'package:cw_core/enumerable_item.dart';
+import 'package:flutter/foundation.dart';
class ListOrderMode extends EnumerableItem<int> with Serializable<int> {
const ListOrderMode({required String title, required int raw}) : super(title: title, raw: raw);
@@ -16,7 +17,10 @@ class ListOrderMode extends EnumerableItem<int> with Serializable<int> {
case 1:
return descending;
default:
- throw Exception('Unexpected token: $raw for ListOrderMode deserialize');
+ if (kDebugMode) {
+ throw Exception('Unexpected token: $raw for ListOrderMode deserialize');
+ }
+ return descending;
}
}
Why this scored 38/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.