Disconnect event triggered right after adding or switching to a custom network (MetaMask 13.7.0 + Web3Auth + wagmi + Next.js)

Environment

  • MetaMask Extension: 13.7.0
  • Framework: Next.js
  • Integration: Web3Auth + wagmi
  • Example Repository: Web3Auth Next.js Quick Start
  • Modification: Only replaced clientId with our own Web3Auth project ID
  • Browser: Chrome 142.0.7444.60

Reproduction Steps

  1. Run the official Web3Auth + wagmi + Next.js example (no code changes except for the clientId).
  2. Connect MetaMask wallet (Connect Wallet button).
  3. Click the “Change Network” button — internally calls
    wallet_addEthereumChain or wallet_switchEthereumChain
    to switch to the custom network configured in the Web3Auth Dashboard.
  4. Immediately after the network switch:```
    • The DApp receives a disconnect event.
      wagmi and Web3Auth update their state to disconnected.

Expected Behavior

  • After adding or switching to a custom network,
    the existing connection/session should remain active.
  • The DApp should not receive a disconnect event
    during a normal network change or addition.

Actual Behavior

  • Right after the network switch, MetaMask emits a disconnect event.
  • wagmi and Web3Auth both update their internal state to “disconnected.”
  • The user must manually reconnect the wallet to continue.
1 Like

Hi 조성혁 — thanks for the clear report. I can see you’re reporting an issue (disconnect event) after adding/switching a custom network while using MetaMask Embedded Wallets (Web3Auth) + wagmi in a Next.js app. I’ve summarized what you provided, suggested quick checks/workarounds, and listed only the additional details the support team will likely need to investigate.

Summary of provided details

  • SDK / integration: MetaMask Embedded Wallets (Web3Auth)
  • MetaMask Extension version: 13.7.0
  • Framework / platform: Next.js (browser: Chrome 142.0.7444.60)
  • Additional libs: wagmi + Web3Auth (example repo: web3auth-examples/quick-starts/nextjs-quick-start at main · Web3Auth/web3auth-examples · GitHub)
  • Change made to example: only replaced clientId with your Web3Auth project ID
  • Repro steps (as provided): connect → call wallet_addEthereumChain / wallet_switchEthereumChain → immediately receives a ‘disconnect’ event (wagmi/Web3Auth go to disconnected)
  • Expected: network switch should not cause disconnect
  • Actual: MetaMask emits ‘disconnect’ immediately after chain add/switch; manual reconnect required

Missing or useful extra info (please share if convenient)

  • Web3Auth SDK version (e.g. @web3auth/web3auth version)
  • wagmi version (and ethers or other provider libs versions if used)
  • Code snippets showing how you initialize Web3Auth / MetaMask Embedded and how you call connect (initialization & login snippets). If you already used the example unmodified other than clientId, indicate that explicitly.
  • Browser console logs captured while reproducing (the console output immediately before/during/after the network switch). A screenshot or copy/paste of the errors is fine — these logs are often the fastest way for the team to locate the cause.

Why we ask for the above

  • Versions of Web3Auth / wagmi are often necessary to reproduce environment-specific behavior. Console logs can show internal errors or provider messages that explain why the provider emitted ‘disconnect’. The init/login snippet confirms whether the embedded provider is being re-initialized or replaced when chain switching occurs.

Quick troubleshooting steps & possible workarounds you can try now

  1. Isolate: attempt the same flow with a plain MetaMask extension (no Web3Auth/wagmi) to check if the extension itself emits disconnect on your machine. If it does not, the issue is likely in the Web3Auth/wagmi flow.
  2. Try a different MetaMask version (or update to the latest if available) and/or a different browser profile to rule out a local regression or extension conflict.
  3. Watch provider events in the console. Add temporary listeners in your app to log events:
    • provider.on(‘chainChanged’, …)
    • provider.on(‘accountsChanged’, …)
    • provider.on(‘disconnect’, …)
      Capture the order of events when you call wallet_addEthereumChain / wallet_switchEthereumChain.
  4. Short-term app workaround: if you must support the flow immediately, handle disconnect by detecting if it coincides with a chainChanged event and automatically attempt to re-connect (call wagmi connect()) rather than treating it as a full user-initiated disconnect. This is a workaround while we validate whether this is an underlying provider bug.

Relevant docs (for quick reference)

If you’d like escalation to the engineering team, please attach the missing items above (especially the Web3Auth/wagmi versions, init/login snippets, and console logs). With those, I’ll file this for deeper investigation and tag the product engineers. If you prefer, paste the console log here and I’ll take a first pass at it.

Would you like me to escalate now, or do you want to paste the small snippets/logs first so I can try a targeted suggestion?

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

Environment

  • wagmi: wagmi@2.19.2
  • web3auth: @web3auth/modal@10.5.6
  • MetaMask Extension: 13.7.0
  • Example Repository: Web3Auth Next.js Quick Start
  • Modification: Only clientId was replaced with our own Web3Auth project ID.

Reproduction Scenario

  1. Use the official Web3Auth + wagmi + Next.js example above.
  2. Launch the DApp and connect MetaMask (Connect Wallet button).
  3. Click “Change Network” (internally calls wallet_switchEthereumChain or wallet_addEthereumChain).
  4. Immediately after the network switch, MetaMask emits a disconnect event → wagmi/Web3Auth change to disconnected.

Connect Call

const { connect } = useWeb3AuthConnect();
...
<button onClick={() => connect()} className="card">
  Login
</button>

Network Switch Code

const { chains, switchChain, error } = useSwitchChain();

const handleSwitchChain = async (targetChainId: number) => {
  try {
    await switchChain({ chainId: targetChainId });
  } catch (err) {
    console.error("❌ switchChain:", err);
  }
};

{chains.map((chain) => (
  <button
    disabled={chainId === chain.id}
    key={chain.id}
    onClick={() => handleSwitchChain(chain.id)}
    type="button"
    className="card"
  >
    {chain.name}
  </button>
))}

MetaMask Service Worker Console Logs

RPC (http://localhost:3000): eth_requestAccounts -> success
RPC (http://localhost:3000): eth_chainId -> success
RPC (http://localhost:3000): eth_accounts -> success
RPC (http://localhost:3000): wallet_switchEthereumChain -> success
RPC (http://localhost:3000): eth_accounts -> success
RPC (http://localhost:3000): eth_chainId -> success
RPC (http://localhost:3000): personal_sign -> success
RPC (http://localhost:3000): eth_chainId -> success
RPC (http://localhost:3000): eth_accounts -> success
RPC (http://localhost:3000): eth_chainId -> success
RPC (http://localhost:3000): wallet_switchEthereumChain -> error
RPC (http://localhost:3000): wallet_addEthereumChain -> success
RPC (http://localhost:3000): eth_chainId -> success
RPC (http://localhost:3000): eth_accounts -> success
RPC (http://localhost:3000): wallet_revokePermissions -> success

Disconnect Event Log

const handleDisconnect = (error: any) => {
  console.error("[DISCONNECT EVENT]", error);
};
ethereum.on?.("disconnect", handleDisconnect);

Output:

[DISCONNECT EVENT] a: MetaMask: Disconnected from chain. Attempting to connect.
    at d._handleDisconnect (inpage.js:1:128967)
    at d._handleDisconnect (inpage.js:1:136682)
    at d._handleChainChanged (inpage.js:1:140854)
    at d._handleChainChanged (inpage.js:1:138490)
    at o.<anonymous> (inpage.js:1:139997)
    at i (inpage.js:1:186318)
    at o.emit (inpage.js:1:186856)
    at inpage.js:1:15135
    at c.write [as _write] (inpage.js:1:15158)
    at j (inpage.js:1:37101)
    at inpage.js:1:40197
    at R.write (inpage.js:1:40224)
    at o.d (inpage.js:1:73267)
    at a.emit (inpage.js:10:30971)
    at A (inpage.js:1:68075)
    at j (inpage.js:1:67905)
    at R.push (inpage.js:1:68689)
    at u._write (inpage.js:1:62438)
    at j (inpage.js:1:80480)
    at inpage.js:1:83576
    at R.write (inpage.js:1:83603)
    at f.d (inpage.js:1:108560)
    at a.emit (inpage.js:10:30971)
    at A (inpage.js:1:103368)
    at j (inpage.js:1:103198)
    at R.push (inpage.js:1:103982)
    at f._onData (inpage.js:1:90665)
    at f._onMessage (inpage.js:1:98568)
overrideMethod	@	installHook.js:1
SwitchChain.useEffect.handleDisconnect	@	switchNetwork.tsx:37
i	@	inpage.js:1
emit	@	inpage.js:1
_handleDisconnect	@	inpage.js:1
_handleDisconnect	@	inpage.js:1
_handleChainChanged	@	inpage.js:1
_handleChainChanged	@	inpage.js:1
(anonymous)	@	inpage.js:1
i	@	inpage.js:1
emit	@	inpage.js:1
(anonymous)	@	inpage.js:1
write	@	inpage.js:1
j	@	inpage.js:1
(anonymous)	@	inpage.js:1
R.write	@	inpage.js:1
d	@	inpage.js:1
a.emit	@	inpage.js:10
A	@	inpage.js:1
j	@	inpage.js:1
R.push	@	inpage.js:1
_write	@	inpage.js:1
j	@	inpage.js:1
(anonymous)	@	inpage.js:1
R.write	@	inpage.js:1
d	@	inpage.js:1
a.emit	@	inpage.js:10
A	@	inpage.js:1
j	@	inpage.js:1
R.push	@	inpage.js:1
_onData	@	inpage.js:1
_onMessage	@	inpage.js:1

Summary

  • Immediately after wallet_addEthereumChain / wallet_switchEthereumChain, MetaMask internally calls _handleDisconnect, which propagates a disconnect event.
  • The issue reproduces consistently in the unmodified Web3Auth + wagmi example.
  • From the logs, a wallet_revokePermissions call appears right before the disconnection.