Skip to content

isMobile() misclassifies narrow desktop viewports, causing WalletConnect to hang instead of showing QR #8968

Description

Version: reproduced on thirdweb@5.119.1; the relevant code is unchanged in 5.121.4 (latest at time of writing).

Summary

On a desktop browser with a viewport narrower than 640px, starting a WalletConnect connection incorrectly takes the mobile deep-link path instead of displaying the QR code.

The result is an infinite spinner and a connection that cannot complete.

Steps to reproduce

  1. Open an app in desktop Chrome with a desktop user agent and no touch screen.
  2. Resize the browser window below 640px, or dock DevTools so the viewport becomes narrower than 640px.
  3. Do not use device emulation.
  4. Start a WalletConnect connection.

Expected: The inline WalletConnect QR code is displayed, as it is at wider viewport sizes.

Actual: The connection shows an infinite spinner.

The console reports:

Failed to launch 'wc:…' because the scheme does not have a registered handler

Widening the viewport above 640px and retrying immediately displays the QR code correctly. We reproduced this at 555px (spinner) versus 1000px (QR) on the same machine, browser, and session.

Root cause

isMobile() treats a viewport narrower than 640px as a mobile device:

export function isMobile() {
  // Primary signal: OS detection via user agent
  const isMobileOS = isAndroid() || isIOS();
  if (isMobileOS) return true;

  // Secondary signal: catch edge cases like webviews with modified user agents
  if (hasTouchScreen() && hasMobileAPIs()) return true;

  const isMobileViewport =
    typeof window !== "undefined" && window.innerWidth < 640;

  if (isMobileViewport) return true;

  return false;
}

create-wallet.js uses isMobile() to choose between the mobile deep-link flow and the desktop QR flow.

When isMobile() returns true, it attempts to open the WalletConnect URI:

openWindow(formatWalletConnectUrl(mobileAppLink, uri).redirect)

or, when no mobile app link is available:

openWindow(uri)

It then returns without reaching the desktop QR-overlay path.

On a real desktop browser there is no wc: URI handler, so the hand-off fails and the connection remains stuck on the spinner.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions