Skip to content

chore(runway): cherry-pick fix: improve Ledger error handling for disconnect, retry, and pagination cp-7.77.0#30190

Merged
chloeYue merged 2 commits into
release/7.77.0from
runway-cherry-pick-7.77.0-1778772183
May 14, 2026
Merged

chore(runway): cherry-pick fix: improve Ledger error handling for disconnect, retry, and pagination cp-7.77.0#30190
chloeYue merged 2 commits into
release/7.77.0from
runway-cherry-pick-7.77.0-1778772183

Conversation

@runway-github

@runway-github runway-github Bot commented May 14, 2026

Copy link
Copy Markdown
Contributor

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 readinessnextPage/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 classificationgetLedgerAccountsByOperation
    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

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

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.

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.

Reviewed by Cursor Bugbot for commit
5e139f5. Bugbot is set up for automated
code reviews on this repo. Configure
here.


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 dc9bd4f

…connect, 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>
@github-actions

Copy link
Copy Markdown
Contributor

CLA Signature Action: All authors have signed the CLA. You may need to manually re-run the blocking PR check if it doesn't pass in a few minutes.

@metamaskbotv2 metamaskbotv2 Bot added the team-bots Bot team (for MetaMask Bot, Runway Bot, etc.) label May 14, 2026

@chloeYue chloeYue left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@codecov-commenter

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 95.45455% with 2 lines in your changes missing coverage. Please review.
⚠️ Please upload report for BASE (release/7.77.0@e0b88b9). Learn more about missing BASE report.

Files with missing lines Patch % Lines
.../HardwareWallet/adapters/LedgerBluetoothAdapter.ts 90.90% 0 Missing and 1 partial ⚠️
app/core/Ledger/Ledger.ts 80.00% 0 Missing and 1 partial ⚠️
Additional details and impacted files
@@                Coverage Diff                @@
##             release/7.77.0   #30190   +/-   ##
=================================================
  Coverage                  ?   81.54%           
=================================================
  Files                     ?     5332           
  Lines                     ?   141643           
  Branches                  ?    32298           
=================================================
  Hits                      ?   115504           
  Misses                    ?    18240           
  Partials                  ?     7899           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@github-actions

Copy link
Copy Markdown
Contributor

🔍 Smart E2E Test Selection

⏭️ Smart E2E selection skipped - PR targets a release branch (release/*)

All E2E tests pre-selected.

View GitHub Actions results

@sonarqubecloud

Copy link
Copy Markdown

@chloeYue chloeYue merged commit e8dcfca into release/7.77.0 May 14, 2026
102 of 104 checks passed
@chloeYue chloeYue deleted the runway-cherry-pick-7.77.0-1778772183 branch May 14, 2026 20:26
@github-actions github-actions Bot locked and limited conversation to collaborators May 14, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

size-L team-bots Bot team (for MetaMask Bot, Runway Bot, etc.)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants