Commit dc9bd4f
fix: improve Ledger error handling for disconnect, retry, and pagination cp-7.77.0 (#28515)
## **Description**
Fixes multiple issues with Ledger hardware wallet error handling that
caused confusing error dialogs when the device was disconnected, the
Ethereum app was closed, or blind signing was disabled:
1. **Stale BLE transport cleanup** — `#closeTransport` now forces BLE
disconnection even when the transport object is already null but a
device ID remains, preventing the OS from keeping a stale connection
that blocks reconnection.
2. **Broader transient error detection** — `#isTransientBleError` now
falls back to message-based matching (e.g. "disconnected", "bluetooth",
"gatt") for BLE errors that use generic `Error` names after a device
power-cycle.
3. **Wrong-app command failure cleanup** — `#handleWrongApp` now closes
the transport when `openEthereumAppOnLedger` or
`closeRunningAppOnLedger` fails, preventing stale connections.
4. **Pagination device readiness** — `nextPage`/`prevPage` in
`LedgerSelectAccount` now call `ensureDeviceReady` before fetching
accounts, and only dismiss the blocking modal if it was actually shown
(via a `modalShown` flag).
5. **Disconnect error classification** — `getLedgerAccountsByOperation`
now detects disconnect errors and throws a user-friendly "device got
disconnected" message instead of a generic error.
6. **Gitignore updates** — Added `.cursor/hooks/state/` to `.gitignore`
to prevent Cursor IDE state files from being committed.
## **Changelog**
CHANGELOG entry: Fixed Ledger hardware wallet error handling to properly
recover from disconnects, app switching failures, and pagination errors
## **Related issues**
Fixes: #28272
## **Manual testing steps**
```gherkin
Feature: Ledger error handling on disconnect
Scenario: User disconnects Ledger during account pagination
Given the user has connected a Ledger device via Bluetooth
And the Ledger Select Account screen is displayed
When the user disconnects the Ledger device
And the user taps Next Page
Then the app should prompt the user to reconnect instead of showing a generic error
Scenario: User switches apps on Ledger during operation
Given the user has connected a Ledger device with the Ethereum app open
When the user switches to a different app on the Ledger
And an operation is attempted
Then the app should detect the transient BLE error and retry the connection
Scenario: Ledger is powered off during account fetch
Given the user has connected a Ledger device via Bluetooth
And the Ledger Select Account screen is displayed
When the user powers off the Ledger device
And the user taps Next Page or Previous Page
Then the app should show a disconnect-specific error message
And the blocking modal should not be incorrectly dismissed
```
## **Screenshots/Recordings**
### **Before**
N/A
### **After**
N/A
## **Pre-merge author checklist**
- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I've included tests if applicable
- [x] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.
## **Pre-merge reviewer checklist**
- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Medium Risk**
> Changes touch Ledger BLE transport cleanup/retry logic and
account-pagination readiness gating, which can affect hardware-wallet
connection stability and user flows. Risk is mitigated by expanded unit
test coverage across adapter, error parsing, and UI pagination cases.
>
> **Overview**
> Improves Ledger Bluetooth robustness by forcing BLE cleanup even when
the transport object is already cleared, and by expanding transient
disconnect detection to include message-based matches; it also closes
the transport when app-switch commands fail to avoid stale connections.
>
> Updates `LedgerSelectAccount` pagination (`nextPage`/`prevPage`) to
call `ensureDeviceReady` before fetching pages and to only dismiss the
blocking modal if it was shown, preventing unnecessary modal flicker and
avoiding pagination attempts when the device isn’t ready.
>
> Enhances Ledger error classification by treating disconnect-like
failures in `getLedgerAccountsByOperation` as a user-facing
“disconnected” error, and broadens `parseErrorByType` to handle
non-`Error` objects with Ledger-shaped `name`/`statusCode`; adds/updates
unit tests across these scenarios.
>
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
5e139f5. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
---------
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Xiaoming Wang <dawnseeker8@users.noreply.github.com>
Co-authored-by: metamaskbot <metamaskbot@users.noreply.github.com>
Co-authored-by: Nico MASSART <NicolasMassart@users.noreply.github.com>1 parent 0c60aeb commit dc9bd4f
10 files changed
Lines changed: 489 additions & 25 deletions
File tree
- app
- components/Views/LedgerSelectAccount
- core
- HardwareWallet
- adapters
- errors
- hooks
- Ledger
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
818 | 818 | | |
819 | 819 | | |
820 | 820 | | |
| 821 | + | |
| 822 | + | |
| 823 | + | |
| 824 | + | |
| 825 | + | |
| 826 | + | |
| 827 | + | |
| 828 | + | |
| 829 | + | |
| 830 | + | |
| 831 | + | |
| 832 | + | |
| 833 | + | |
| 834 | + | |
| 835 | + | |
| 836 | + | |
| 837 | + | |
| 838 | + | |
| 839 | + | |
| 840 | + | |
| 841 | + | |
| 842 | + | |
| 843 | + | |
| 844 | + | |
| 845 | + | |
| 846 | + | |
| 847 | + | |
| 848 | + | |
| 849 | + | |
| 850 | + | |
| 851 | + | |
| 852 | + | |
| 853 | + | |
| 854 | + | |
| 855 | + | |
| 856 | + | |
| 857 | + | |
| 858 | + | |
| 859 | + | |
| 860 | + | |
| 861 | + | |
| 862 | + | |
| 863 | + | |
| 864 | + | |
| 865 | + | |
| 866 | + | |
| 867 | + | |
| 868 | + | |
| 869 | + | |
| 870 | + | |
| 871 | + | |
| 872 | + | |
| 873 | + | |
| 874 | + | |
| 875 | + | |
| 876 | + | |
| 877 | + | |
| 878 | + | |
| 879 | + | |
| 880 | + | |
| 881 | + | |
| 882 | + | |
| 883 | + | |
| 884 | + | |
| 885 | + | |
| 886 | + | |
| 887 | + | |
| 888 | + | |
| 889 | + | |
| 890 | + | |
| 891 | + | |
| 892 | + | |
| 893 | + | |
| 894 | + | |
| 895 | + | |
| 896 | + | |
| 897 | + | |
| 898 | + | |
| 899 | + | |
| 900 | + | |
| 901 | + | |
| 902 | + | |
| 903 | + | |
| 904 | + | |
| 905 | + | |
| 906 | + | |
| 907 | + | |
| 908 | + | |
| 909 | + | |
| 910 | + | |
| 911 | + | |
| 912 | + | |
| 913 | + | |
| 914 | + | |
| 915 | + | |
| 916 | + | |
| 917 | + | |
| 918 | + | |
| 919 | + | |
| 920 | + | |
| 921 | + | |
| 922 | + | |
| 923 | + | |
| 924 | + | |
| 925 | + | |
| 926 | + | |
| 927 | + | |
| 928 | + | |
| 929 | + | |
| 930 | + | |
| 931 | + | |
| 932 | + | |
| 933 | + | |
| 934 | + | |
| 935 | + | |
| 936 | + | |
| 937 | + | |
| 938 | + | |
| 939 | + | |
| 940 | + | |
| 941 | + | |
| 942 | + | |
| 943 | + | |
| 944 | + | |
821 | 945 | | |
822 | 946 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
222 | 222 | | |
223 | 223 | | |
224 | 224 | | |
225 | | - | |
| 225 | + | |
226 | 226 | | |
| 227 | + | |
| 228 | + | |
| 229 | + | |
| 230 | + | |
| 231 | + | |
227 | 232 | | |
228 | 233 | | |
229 | 234 | | |
230 | 235 | | |
231 | 236 | | |
232 | 237 | | |
233 | 238 | | |
234 | | - | |
| 239 | + | |
| 240 | + | |
| 241 | + | |
235 | 242 | | |
236 | | - | |
| 243 | + | |
237 | 244 | | |
238 | 245 | | |
239 | | - | |
| 246 | + | |
240 | 247 | | |
| 248 | + | |
| 249 | + | |
| 250 | + | |
| 251 | + | |
| 252 | + | |
241 | 253 | | |
242 | 254 | | |
243 | 255 | | |
244 | 256 | | |
245 | 257 | | |
246 | 258 | | |
247 | 259 | | |
248 | | - | |
| 260 | + | |
| 261 | + | |
| 262 | + | |
249 | 263 | | |
250 | | - | |
| 264 | + | |
251 | 265 | | |
252 | 266 | | |
253 | 267 | | |
| |||
Lines changed: 190 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
271 | 271 | | |
272 | 272 | | |
273 | 273 | | |
| 274 | + | |
| 275 | + | |
| 276 | + | |
| 277 | + | |
| 278 | + | |
| 279 | + | |
| 280 | + | |
| 281 | + | |
| 282 | + | |
| 283 | + | |
| 284 | + | |
| 285 | + | |
| 286 | + | |
| 287 | + | |
| 288 | + | |
| 289 | + | |
| 290 | + | |
| 291 | + | |
| 292 | + | |
| 293 | + | |
| 294 | + | |
274 | 295 | | |
275 | 296 | | |
276 | 297 | | |
| |||
625 | 646 | | |
626 | 647 | | |
627 | 648 | | |
| 649 | + | |
| 650 | + | |
| 651 | + | |
| 652 | + | |
| 653 | + | |
| 654 | + | |
| 655 | + | |
| 656 | + | |
| 657 | + | |
| 658 | + | |
| 659 | + | |
| 660 | + | |
| 661 | + | |
| 662 | + | |
| 663 | + | |
628 | 664 | | |
629 | 665 | | |
630 | 666 | | |
| |||
687 | 723 | | |
688 | 724 | | |
689 | 725 | | |
| 726 | + | |
| 727 | + | |
| 728 | + | |
| 729 | + | |
| 730 | + | |
| 731 | + | |
| 732 | + | |
| 733 | + | |
| 734 | + | |
| 735 | + | |
| 736 | + | |
| 737 | + | |
| 738 | + | |
| 739 | + | |
| 740 | + | |
| 741 | + | |
| 742 | + | |
| 743 | + | |
| 744 | + | |
| 745 | + | |
| 746 | + | |
| 747 | + | |
| 748 | + | |
| 749 | + | |
| 750 | + | |
| 751 | + | |
| 752 | + | |
| 753 | + | |
| 754 | + | |
| 755 | + | |
| 756 | + | |
| 757 | + | |
| 758 | + | |
| 759 | + | |
| 760 | + | |
| 761 | + | |
| 762 | + | |
| 763 | + | |
| 764 | + | |
| 765 | + | |
| 766 | + | |
| 767 | + | |
| 768 | + | |
| 769 | + | |
| 770 | + | |
| 771 | + | |
| 772 | + | |
| 773 | + | |
| 774 | + | |
| 775 | + | |
| 776 | + | |
| 777 | + | |
| 778 | + | |
| 779 | + | |
| 780 | + | |
| 781 | + | |
| 782 | + | |
| 783 | + | |
| 784 | + | |
| 785 | + | |
| 786 | + | |
| 787 | + | |
| 788 | + | |
| 789 | + | |
| 790 | + | |
| 791 | + | |
| 792 | + | |
| 793 | + | |
| 794 | + | |
| 795 | + | |
| 796 | + | |
| 797 | + | |
| 798 | + | |
| 799 | + | |
| 800 | + | |
| 801 | + | |
| 802 | + | |
| 803 | + | |
| 804 | + | |
| 805 | + | |
| 806 | + | |
| 807 | + | |
| 808 | + | |
| 809 | + | |
| 810 | + | |
| 811 | + | |
| 812 | + | |
| 813 | + | |
| 814 | + | |
| 815 | + | |
| 816 | + | |
| 817 | + | |
| 818 | + | |
| 819 | + | |
| 820 | + | |
| 821 | + | |
| 822 | + | |
| 823 | + | |
| 824 | + | |
| 825 | + | |
| 826 | + | |
| 827 | + | |
| 828 | + | |
| 829 | + | |
| 830 | + | |
| 831 | + | |
| 832 | + | |
| 833 | + | |
| 834 | + | |
| 835 | + | |
| 836 | + | |
| 837 | + | |
| 838 | + | |
| 839 | + | |
| 840 | + | |
| 841 | + | |
| 842 | + | |
| 843 | + | |
| 844 | + | |
| 845 | + | |
| 846 | + | |
| 847 | + | |
| 848 | + | |
| 849 | + | |
| 850 | + | |
| 851 | + | |
| 852 | + | |
| 853 | + | |
| 854 | + | |
| 855 | + | |
| 856 | + | |
| 857 | + | |
| 858 | + | |
| 859 | + | |
| 860 | + | |
| 861 | + | |
| 862 | + | |
| 863 | + | |
| 864 | + | |
| 865 | + | |
| 866 | + | |
| 867 | + | |
| 868 | + | |
| 869 | + | |
| 870 | + | |
| 871 | + | |
| 872 | + | |
| 873 | + | |
| 874 | + | |
| 875 | + | |
| 876 | + | |
| 877 | + | |
| 878 | + | |
| 879 | + | |
690 | 880 | | |
691 | 881 | | |
692 | 882 | | |
| |||
0 commit comments