Connection Issues in ANdroid

  • Describe your issue or question:

    • web page built on Vue2.

    • using @web3auth/modal": "^10.5.4

    • connection in desktop works fine, but in android mobiles is not working, in iphone works but connection is super slow.

    • Before migration to version 10, it worked fine. Web3auth initialization was being made in first rendering, but this was causing problems with other wallets connections, so initialization now is made only when user chooses web3auth. For this, it was necessary to set a timeout to give it time to be ready before trying to connect.

  • Code snippets:

[constants.SESSION_CONNECT_WEB3AUTH]: async (

    { commit, dispatch, state },

    { loginProvider }

  ) => {

setWalletConnectionEventMP(EVENT_NAME.WCS, 'WEB3AUTH');

commit(constants.SESSION_SET_PROPERTY, { showDialogConnect: false });

const { chainId } = state;

try {

const web3AuthInstance = await web3AuthInit(chainId);

if (web3AuthInstance && (web3AuthInstance.connected === true

|| web3AuthInstance.status === 'connected'

|| (web3AuthInstance.state && web3AuthInstance.state.cachedConnector))) {

try { await web3AuthInstance.logout(); } catch (e) {}

       }

const localProvider = await web3AuthInstance.connectTo(WALLET_CONNECTORS.AUTH, {

authConnection: loginProvider,

      })

Vue.prototype.$web3 = Vue.web3 = new ethers.providers.Web3Provider(localProvider, 'any');




Vue.prototype.$tropykus = Vue.tropykus = new Tropykus(Vue.web3, null, 900000);

Vue.tropykus.setPriceOracle(addresses[chainId].priceOracleProxy);




const tropykusAccount = await Vue.tropykus.getAccount();




const tropykusComptroller = await Vue.tropykus.setComptroller(

tropykusAccount,

addresses[chainId].comptroller

      );

const tropykusMkts = await tropykusComptroller.getAllMarketsInstances(

addresses[chainId].kSAT,

addresses[chainId].kRBTC,

addresses[chainId].krDOC

      );




const tropykus = {

account: tropykusAccount,

comptroller: tropykusComptroller,

mkts: tropykusMkts,

      };




const account = await Vue.web3.getSigner();

const walletAddress = await account.getAddress();

const clientInformation = getInfoNavigation();

const mappedClientInformation = {

browser: clientInformation.browser,

browser_version: clientInformation.browser_version,

os: clientInformation.os,

isMobile: clientInformation.isMobile,

os_version: clientInformation.os_version,

      };

commit(constants.SESSION_SET_PROPERTY, { clientInformation: mappedClientInformation });




commit(constants.SESSION_SET_PROPERTY, { chainId });

commit(constants.SESSION_SET_PROPERTY, { tropykus });

commit(constants.SESSION_SET_PROPERTY, { provider: Vue.web3 });

commit(constants.SESSION_SET_PROPERTY, { account });

commit(constants.SESSION_SET_PROPERTY, { walletAddress });

commit(constants.SESSION_SET_PROPERTY, { wallet: 'WEB3AUTH' });

dispatch(constants.SESSION_GET_USER_ID, { walletAddress, source: 'fromSession' });

dispatch(constants.SESSION_SET_TROPK_PROVIDER);

dispatch(constants.SESSION_GET_EXPLORER, chainId);

setWalletConnectionEventMP(EVENT_NAME.WCC, 'WEB3AUTH');

return localProvider;

    } catch (error) {

const dataError = {

message: error?.message,

error,

      }

const info = (typeof mappedClientInformation !== 'undefined' && mappedClientInformation) ? mappedClientInformation : getInfoNavigation();

postLogs({

type: 'error',

description: 'error session connect web3auth',

wallet_type: 'WEB3AUTH',

address: typeof walletAddress !== 'undefined' ? walletAddress : constants.ADDRESS_ZERO,

data: dataError,

client_information: info,

      });

setWalletConnectionEventMP(EVENT_NAME.WCE, 'WEB3AUTH', dataError);

    }

  },
export async function web3AuthInit(chainId) {

  const clientId = process.env.VUE_APP_CLIENT_ID;

const network = chainId === 30 ? WEB3AUTH_NETWORK.MAINNET : WEB3AUTH_NETWORK.TESTNET;

const web3AuthOptions = {

clientId,

web3AuthNetwork: network,

whiteLabel: {

name: 'Tropykus',

url: 'https://tropykus.finance',

logoLight: '
',

logoDark: '
',

defaultLanguage: 'es',

dark: false,

theme: {

primary: '#00D1B2',

      },

    },

  };




const web3AuthInstance = new Web3Auth(web3AuthOptions);

await web3AuthInstance.init();

await new Promise((resolve, reject) => {

let interval;

const timeout = setTimeout(() => {

if (interval) clearInterval(interval);

reject(new Error('Timeout esperando Web3Auth.connected'));

    }, 15000);




interval = setInterval(() => {

const connected = web3AuthInstance.status === 'ready';




if (connected) {

clearInterval(interval);

clearTimeout(timeout);

resolve();

      }

    }, 200);

  });

setWeb3AuthInstance(web3AuthInstance);

return web3AuthInstance;

}
  • Exact error and logs:

  • One of the errors I get in android is this one:
    {“error”:{},“message”:“Timeout esperando Web3Auth.connected”}, this means web3auth initizlization is not posible despite the timeout set in web3AuthInit function.
    Another error is this one, despite user does not close the popup beacuse it never shows.

    {
    
            "id": 1281,
    
    "type": "error",
    
    "data": {
    
    "error": {
    
    "code": 5113,
    
    "name": "LoginError",
    
    "message": "login popup has been closed by the user, "
    
                },
    
    "message": "login popup has been closed by the user, "
    
            },
    
    "description": "error session connect web3auth",
    
    "address": "0x0000000000000000000000000000000000000000",
    
    "wallet_type": "WEB3AUTH",
    
    "client_information": {
    
    "os": "Android",
    
    "browser": "Chrome",
    
    "isMobile": true,
    
    "os_version": "Android 10",
    
    "browser_version": "141.0.0.0"
    
            },
    
    "created_at": "2025-10-27T15:04:13.621Z"
    
        },
    
  • Package details:@web3auth/ethereum-provider”: “^9.7.0”,

    "@web3auth/modal": "^10.5.4",
    

Hi Natalia — thanks for the clear report and code sample. I hear you: desktop works but Android fails (and iPhone is extremely slow). I pulled the key details and wrote a concise summary for the support team, plus likely causes and targeted next steps you can try. If you prefer, I can open the ticket with this exact info.

Summary (extracted from your message)

  • SDK / integration: MetaMask Embedded Wallets (using Web3Auth)
  • Packages & versions provided: @web3auth/modal “^10.5.4”, @web3auth/ethereum-provider “^9.7.0”
  • Platform(s) affected: Android (Chrome on Android 10 — popup never shows; timeout on web3Auth.init). iPhone: connection works but very slow.
  • App framework: Vue 2
  • Behavior: web3AuthInit() times out on Android (your custom 15s timeout). Some attempts return LoginError code 5113 “login popup has been closed by the user” even though popup never appears. Worked before upgrading to v10; you moved initialization to only when user chooses Web3Auth and added a timeout to wait until ready.
  • Code snippets attached: web3AuthInit() and SESSION_CONNECT_WEB3AUTH action (connectTo usage). Good: you included init/connect flow and error logs.

Most relevant hypotheses / root causes

  1. Popup-blocking / user-gesture: Browsers (especially mobile) often block popups if the popup is not opened synchronously inside a user-initiated event. From your description you initialize and then await readiness (using a timeout) before calling connectTo — that breaks the “same user gesture” requirement and commonly causes the error that the popup was closed or never opened. Desktop is more permissive; mobile Chrome / WebView is stricter.

  2. In-app WebView vs full browser: If the page is running inside an embedded WebView (e.g., inside an Android app, Facebook in-app browser, or some custom WebView), the Web3Auth modal/popups might not open or behave correctly. The UA/Chrome version in your logs (141.0.0.0) suggests it might be a WebView-like environment.

  3. Cross-origin / cookie / secure context issues: Mobile browsers with strict third-party cookie or cross-origin policies can interfere with popup-based OAuth flows. Also make sure the site is served over HTTPS and the origin matches the clientId settings in Web3Auth dashboard.

  4. Version / API usage: v10 changed some behaviors. Ensure you’re using the recommended modal/provider APIs for mobile. Consider upgrading to latest patch versions — sometimes fixes for mobile popup/redirect handling are included.

Actionable recommendations (quick, prioritized)

  1. Ensure connectTo (login popup) runs synchronously inside the user’s click handler. Don’t await long initialization after the click. Option A: initialize Web3Auth on page load (init only) so connectTo can run directly on click. Option B: start the connect/openLogin directly inside the click (no intervening asynchronous waits that break the gesture).

    • Example approach: create the Web3Auth instance eagerly (new Web3Auth(…); await init() on page load) but only call connectTo when the user clicks. That avoids popup blocking while not showing the modal until asked.
  2. If you must initialize at click time and init() is async, use a redirect login flow for mobile (if Web3Auth supports it) rather than a popup, or show an in-page loading state and open the popup from a user-gesture-friendly API right away.

  3. Confirm you are running in a full Chrome browser and not a restricted WebView. If it is a WebView, try testing in Chrome browser on the same device to compare. If you need to run inside WebView, check Web3Auth docs for supported mobile flows or consider deep-link / universal-link configuration.

  4. Check origins/redirect URIs / clientId settings in your Web3Auth dashboard and ensure HTTPS and origin are correct for mobile. Also test with third-party cookies enabled (or check Web3Auth mobile recommendations).

  5. Try upgrading @web3auth/modal and @web3auth/ethereum-provider to latest patch versions if possible — mobile modal fixes are sometimes shipped in patch releases.

  6. Increase diagnostic logging: capture browser console logs and network logs during the mobile attempt. This will help find if requests are blocked or if errors happen before popup creation.

What I still need from you (only if you can share — I don’t want to spam you):

  • Are you running inside an embedded WebView (a mobile app) or in Chrome/Edge/Samsung Internet as a normal tab? (This is important.)
  • A short copy of the browser console logs from Android (especially around the init/connect calls) or a screenshot of the console/network timeline. You already shared the timeout and 5113 error which is helpful.
  • Confirm origin/protocol (is the page served via HTTPS in production?).

Useful references

  • MetaMask docs (general integration info): https://docs.metamask.io
  • Web3Auth best-practices for mobile/login flows — check your Web3Auth modal docs and mobile/redirect guidance in the Web3Auth docs (they cover popup vs redirect and WebView support).

If you want, I can:

  • Suggest a small code change to ensure connectTo is called synchronously on click (I can show a minimal pattern), or
  • Draft a support ticket for you including the summary above and the logs you already pasted.

Which would you prefer? If you want a code example to run connectTo on user click without losing the user-gesture, tell me whether you can initialize Web3Auth on page load (yes/no) and I’ll return a tiny code pattern tuned for Vue2.

Note: This response was generated by an AI bot and may require further verification. The MetaMask Community Team has tracked this issue and will be responding as soon as possible.

Additionally, we would recommend you to join our biweekly Office Hours to get this resolved even faster. MetaMask Developer Office Hours

no, i cannot initialize Web3Auth on page load becuse this was causing troubles with other wallets connection in mobile. Because of this, initialization was moved inside web3auth connection logic itself.

following your suggestions, the connection problem in Android is solved, but in iphones, the issue persists. I also upgraded @web3auth/modal to version 10.8.

This is the new codebase:

web3Auth.js:

import { WEB3AUTH_NETWORK, Web3Auth } from '@web3auth/modal';




let instance = null;

function setWeb3AuthInstance(newInstance) {

instance = newInstance;

return instance;

}

export function getWeb3AuthInstance() {

return instance;

}




export async function web3AuthInit() {

const clientId = process.env.VUE_APP_CLIENT_ID;

const rawChainId = process.env.VUE_APP_DEFAULT_CHAIN_ID;

const chainId = Number(rawChainId);




if (!rawChainId || Number.isNaN(chainId)) {

throw new Error('VUE_APP_DEFAULT_CHAIN_ID must be a valid number (e.g. "30" or "31")');

  }




const network = chainId === 30 ? WEB3AUTH_NETWORK.MAINNET : WEB3AUTH_NETWORK.TESTNET;




const web3AuthOptions = {

clientId,

web3AuthNetwork: network,

whiteLabel: {

name: 'Tropykus',

url: 'https://tropykus.finance',

logoLight: '
',

logoDark: '
',

defaultLanguage: 'es',

dark: false,

theme: {

primary: '#00D1B2',

      },

    },

  };




const web3AuthInstance = new Web3Auth(web3AuthOptions);

await web3AuthInstance.init();

setWeb3AuthInstance(web3AuthInstance);

return web3AuthInstance;

}

IThe initialization is done in a different view than the login view so that the instance is ready when the user logs in:

Web3AuthLOginView:

… async created() {

   this.setSessionProperty({ showDialogConnect: false });

const web3AuthInstance = await web3AuthInit();

const interval = setInterval(() => {

if (web3AuthInstance.status === 'ready' || web3AuthInstance.status === 'connecting') {

this.instanceReady = true;

clearInterval(interval);

    }

   }, 1000);

  },

And when user chooses the login provider method this function is executed:

[constants.SESSION_CONNECT_WEB3AUTH]: async (

    { commit, dispatch, state },

    { loginProvider, login_hint }

  ) => {

commit(constants.SESSION_SET_PROPERTY, { connectingWeb3Auth: true });

setWalletConnectionEventMP(EVENT_NAME.WCS, 'WEB3AUTH');

commit(constants.SESSION_SET_PROPERTY, { showDialogConnect: false });

const { chainId } = state;

try {

const web3AuthInstance = getWeb3AuthInstance();

if (web3AuthInstance && (web3AuthInstance.connected === true

|| web3AuthInstance.status === 'connected'

|| (web3AuthInstance.state && web3AuthInstance.state.cachedConnector))) {

try { await web3AuthInstance.logout(); } catch (e) {}

       }

const localProvider = await web3AuthInstance.connectTo(WALLET_CONNECTORS.AUTH, {

authConnection: loginProvider, 

loginHint: login_hint

        }) 

commit(constants.SESSION_SET_PROPERTY, { connectingWeb3Auth: false });

....

return localProvider;

    } catch (error) {

commit(constants.SESSION_SET_PROPERTY, { connectingWeb3Auth: false });

const dataError = {

message: error?.message,

error,

      }

const info = (typeof mappedClientInformation !== 'undefined' && mappedClientInformation) ? mappedClientInformation : getInfoNavigation();

postLogs({

type: 'error',

description: 'error session connect web3auth',

wallet_type: 'WEB3AUTH',

address: typeof walletAddress !== 'undefined' ? walletAddress : constants.ADDRESS_ZERO,

data: dataError,

client_information: info,

      });

setWalletConnectionEventMP(EVENT_NAME.WCE, 'WEB3AUTH', dataError);

    }

  },

whit these changes on my codebase, connection works in Android but still fails with Iphones, These are the error logs trying to connect with IOs:

...
message: "log created"

meta: {

address: "0x0000000000000000000000000000000000000000"

client_information: {

browser: "Safari"

isMobile: true

os: "iOS"

os_version: "iOS 18.7"

}

created_at: "2025-12-02T21:07:33.302Z"

data: {

error: {

code: 5114

message: "Wallet popup has been closed by the user. "

name: "WalletLoginError"

}

message: "Wallet popup has been closed by the user. "

}

description: "error session connect web3auth"

type: "error"

wallet_type: "WEB3AUTH"

}

scope: "logs"

ts: "2025-12-02T21:07:33.302Z"