Skip to content

fix(mm_connect): report deeplink failures to Sentry#30343

Merged
adonesky1 merged 2 commits into
mainfrom
fix/sdk-connect-v2-deeplink-sentry
May 21, 2026
Merged

fix(mm_connect): report deeplink failures to Sentry#30343
adonesky1 merged 2 commits into
mainfrom
fix/sdk-connect-v2-deeplink-sentry

Conversation

@adonesky1

@adonesky1 adonesky1 commented May 18, 2026

Copy link
Copy Markdown
Contributor

Description

The SDK-V2 ConnectionRegistry catches errors in handleMwpDeeplink and handleConnectDeeplink and routes them through a local logger (app/core/SDKConnectV2/services/logger.ts) that just prefixes and calls console.error. The app's Sentry init (app/util/sentry/utils.ts) only wires up dedupeIntegration and extraErrorDataIntegration — there's no captureConsoleIntegration — so those errors (including the well-known \"Failed to handle connect deeplink\" string) are silently dropped and never reach Sentry in production.

The only existing signal for these failures is the failure_reason property on the REMOTE_CONNECTION_REQUEST_FAILED MetaMetrics event, which is useful for aggregate counts but provides no stack trace, no breadcrumbs, and no context.

This PR wires both deeplink-entry catch sites to Logger.error from app/util/Logger, which already calls captureException inside a Sentry scope, respects the metrics opt-in, and supports tags/context. The existing logger.error console output is kept so local debugging is unchanged (and Logger.error is a no-op in __DEV__ anyway).

What's reported

  • Tags (searchable in Sentry):
    • `feature: 'mm-connect'` — intentionally uses the public-facing product name even though the directory/class still use the older `SDKConnectV2` nomenclature. There's an inline comment in the code making this explicit; the internal naming needs to migrate but tagging Sentry with the public name now avoids renaming dashboards/alerts later.
    • `operation: 'handle_mwp_deeplink'` | `'handle_connect_deeplink'`
  • Context (`mwp_deeplink`):
    • `url` (redacted via `redactUrl` — query/fragment stripped)
    • For `handle_connect_deeplink`: `dapp_url`, `dapp_name`, `sdk_version`, `sdk_platform` (when the connection request parsed successfully; gracefully `undefined` when parse failed)

Scope is intentionally limited to the two deeplink-entry catches — the most user-impactful failures, triggered directly by an incoming deeplink. The other `console.error`-only sites in the registry (`initialize`, `evictIfAtCapacity`, `reconnectAll`, `handleSimpleDeeplink` 'not found' log) can be addressed in a follow-up if useful.

Changelog

CHANGELOG entry: null

Related issues

Fixes:

Companion PR (provides the QA test surface): feat(playground): add MWP deeplink failure repro panel.

Manual testing steps

Easiest way to exercise every branch reproducibly: use the companion playground PR linked above. It adds a collapsible QA: MWP deeplink failure repros card with one tappable deeplink per failure branch. Without that PR you can still test by manually constructing deeplinks (URLs documented in the playground PR description and table).

Setup

  1. Install a debug build of this PR's branch on a real device (Sentry is disabled in E2E / when `MM_SENTRY_DSN` is missing — see `app/util/sentry/utils.ts` `setupSentry`).
  2. Accept the metrics opt-in during onboarding (Sentry `captureException` only fires when `METRICS_OPT_IN === AGREED`).
  3. From a desktop browser, deploy or run the playground branch from connect-monorepo PR #300 and open it on the device's mobile browser. Expand the QA: MWP deeplink failure repros section.

Feature: SDK-V2 deeplink failure observability

Scenario: parse failure produces a Sentry event with gracefully missing dapp metadata
Given the device is set up per the Setup steps above

When the user taps the Tap on mobile button on the Payload is not valid JSON row
Then the MetaMask Mobile app opens and shows a Connection failed toast
And a `REMOTE_CONNECTION_REQUEST_FAILED` MetaMetrics event fires with `failure_reason` containing `SyntaxError` or similar JSON parse text
And a Sentry event is captured with:
- tag `feature: mm-connect`
- tag `operation: handle_connect_deeplink`
- context `mwp_deeplink.url` ending in `[REDACTED]`
- context `mwp_deeplink.dapp_url`, `dapp_name`, `sdk_version`, `sdk_platform` all `undefined` (because parsing failed before `connReq` was assigned)

Scenario: handshake failure produces a Sentry event with full dapp/sdk context
Given the device is set up per the Setup steps above

When the user taps the Tap on mobile button on the Control: well-formed connect deeplink row
Then the deeplink parses successfully (the dapp metadata is well-formed) but the relay handshake will time out / fail because no wallet is on the other end of the fake session id
And a Sentry event is captured with:
- tag `feature: mm-connect`
- tag `operation: handle_connect_deeplink`
- context `mwp_deeplink.dapp_url: "https://playground.metamask.io\"\`
- context `mwp_deeplink.dapp_name: "MMC Playground (QA Repro)"`
- context `mwp_deeplink.sdk_version: "0.0.0-qa-repro"`
- context `mwp_deeplink.sdk_platform: "JavaScript"`

Scenario: each remaining failure branch is observable
Given the device is set up per the Setup steps above

When the user taps each of the remaining rows (No payload param, Payload parses but is not a ConnectionRequest, sessionRequest.id is not a UUID, dapp.url claims to be an internal origin, c=1 flag but plain payload, Payload over 1MB)
Then each one produces both a `REMOTE_CONNECTION_REQUEST_FAILED` MetaMetrics event and a Sentry event tagged `feature: mm-connect`, `operation: handle_connect_deeplink`

Scenario (regression): existing deeplink flow is unchanged
Given the device has an existing persisted MWP connection from a real dapp

When the user re-opens the dapp and triggers the resume connection flow (simple deeplink with `?id=…`)
Then nothing in the connection flow has changed; no new Sentry events are emitted unless the inner flow actually throws

Verifying in Sentry

In the project Sentry dashboard:

  1. Filter by `feature:mm-connect` → only the new events from this PR should appear.
  2. Filter by `operation:handle_connect_deeplink` vs `handle_mwp_deeplink` to separate the connect-flow failures from the wrapper-dispatch failures.
  3. On any event, the Additional Data panel should show the `mwp_deeplink` context block with the redacted URL and dapp/sdk fields.

Screenshots/Recordings

N/A — observability-only change, no user-visible UI difference.

Before

Failures in MWP deeplink dispatch logged only to the device console; no Sentry event.

After

Failures captured in Sentry with searchable tags and dapp/sdk context. Existing console.error preserved for local debugging.

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.

The SDK-V2 connection registry's catch blocks for handleMwpDeeplink and
handleConnectDeeplink were only routing errors through a local logger
that calls console.error with a prefix. The app's Sentry init does not
include captureConsoleIntegration, so these errors (including the
"Failed to handle connect deeplink" string) were silently dropped and
invisible in production observability — leaving the failure_reason
property on the REMOTE_CONNECTION_REQUEST_FAILED MetaMetrics event as
the only signal, with no stack trace.

Wire both catch sites to Logger.error from app/util/Logger so failures
hit captureException via a Sentry scope, with searchable tags
(feature, operation) and contextual data (redacted URL, dapp metadata,
SDK version/platform). The existing logger.error console output is
kept so local debugging is unchanged.
@adonesky1 adonesky1 requested a review from a team as a code owner May 18, 2026 20:51
@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-wallet-integrations Wallet Integrations team label May 18, 2026

@cursor cursor Bot 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.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit c451bf2. Configure here.

);
});

it('should report dispatch failures to Sentry via Logger.error', async () => {

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.

New test names use banned "should" prefix

Low Severity

All three new test names start with "should", which is banned by the unit testing guidelines ("NEVER use 'should' in test names — this is a hard rule with zero exceptions"). The tests 'should report dispatch failures to Sentry via Logger.error', 'should report connect failures to Sentry with dapp/sdk context', and 'should report parse failures to Sentry even when no connection request is available' need action-oriented names instead, e.g. 'reports dispatch failures to Sentry via Logger.error'.

Additional Locations (2)
Fix in Cursor Fix in Web

Triggered by project rule: Unit Testing Guidelines

Reviewed by Cursor Bugbot for commit c451bf2. Configure here.

The feature tag now uses the public-facing product name "MetaMask
Connect" (mm-connect) so Sentry dashboards/alerts align with the
external naming. Added an inline comment at both catch sites
acknowledging that the surrounding code (directory `SDKConnectV2/`,
class `ConnectionRegistry`, log prefix `[SDKConnectV2]`) still uses
the older nomenclature and needs to migrate.
@github-actions

Copy link
Copy Markdown
Contributor

🔍 Smart E2E Test Selection

  • Selected E2E tags: None (no tests recommended)
  • Selected Performance tags: None (no tests recommended)
  • Risk Level: low
  • AI Confidence: 95%
click to see 🤖 AI reasoning details

E2E Test Selection:
The PR adds Logger.error calls (for Sentry reporting) inside two existing catch blocks in ConnectionRegistry.handleMwpDeeplink and handleConnectDeeplink. These are error-path-only changes:

  1. No behavioral changes to happy paths: The normal deeplink connection flow is completely unaffected. The new Logger.error calls only execute when an error is already thrown.
  2. No new code paths: The catch blocks already existed; only Sentry reporting was added.
  3. Contained scope: connection-registry.ts is only imported by SDKConnectV2/index.ts and its own test file. The SDKConnectV2 index is imported by many test files but not in ways that would affect E2E flows.
  4. Unit test coverage: The test file adds 3 new unit tests specifically validating the new Logger.error behavior, providing adequate coverage.
  5. No UI/UX changes: No components, screens, or user-facing flows are modified.

No E2E tags are needed — this is a pure observability/error-reporting improvement with no risk to existing functionality.

Performance Test Selection:
The changes only add Logger.error calls in catch blocks. There is zero performance impact on any user-facing flow, rendering, data loading, or app startup.

View GitHub Actions results

@sonarqubecloud

Copy link
Copy Markdown

@adonesky1 adonesky1 changed the title fix(sdk-connect-v2): report deeplink failures to Sentry fix(mm_connect): report deeplink failures to Sentry May 18, 2026
@adonesky1 adonesky1 added this pull request to the merge queue May 21, 2026
@github-merge-queue github-merge-queue Bot removed this pull request from the merge queue due to failed status checks May 21, 2026
@adonesky1 adonesky1 added this pull request to the merge queue May 21, 2026
Merged via the queue into main with commit 2847b52 May 21, 2026
136 of 139 checks passed
@adonesky1 adonesky1 deleted the fix/sdk-connect-v2-deeplink-sentry branch May 21, 2026 19:06
@github-actions github-actions Bot locked and limited conversation to collaborators May 21, 2026
@metamaskbotv2 metamaskbotv2 Bot added the release-7.79.0 Issue or pull request that will be included in release 7.79.0 label May 21, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

release-7.79.0 Issue or pull request that will be included in release 7.79.0 size-M team-wallet-integrations Wallet Integrations team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants