You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Calling connect({ connector: portoConnector }) again does nothing — no dialog, no error
Expected Behavior
After disconnect() + page reload, either:
Successfully restore the session with a valid address, OR
Report isConnected: false so the app can show a clean login flow
What I See in Storage
After the ghost state occurs:
wagmi.recentConnectorId still set to "xyz.ithaca.porto" in localStorage
wagmi.store in localStorage has connections Map with empty value: []
Porto's IndexedDB (porto database, store object store) still exists with a porto.store entry containing {state: Object, version: 5}
Manually deleting the Porto IndexedDB + wagmi localStorage keys and reloading fixes it.
Possible Root Cause
Looking at Porto's source, I suspect a persistence timing issue:
wallet_disconnect in provider.ts calls store.setState((x) => ({ ...x, accounts: [] })) — this updates memory, but the zustand persist write to IndexedDB is async. If the page unloads before the write completes, stale account data survives in IndexedDB.
waitForHydration in store.ts has a setTimeout(() => resolve(true), 100) fallback. If IndexedDB hydration is slower than 100ms (common on mobile/cold start), the provider may initially read empty state, then hydration completes later with stale accounts, firing a late connect event that creates the ghost state after wagmi already decided "not authorized."
The wagmi connector's connect() with isReconnecting: true returns { accounts: [], chainId } instead of failing when no accounts are found — wagmi stores this as a "connected" connection with zero accounts.
Workaround
We currently work around this by:
Detecting ghost state (account.isConnected && !account.address) before calling connect(), and calling disconnectAsync() first
Clearing Porto's IndexedDB (indexedDB.deleteDatabase('porto')) during logout
Also clearing wagmi.store and wagmi.recentConnectorId from localStorage during logout
Description
After disconnecting a Porto passkey wallet via wagmi's
disconnect(), subsequent page reloads result in a "ghost-connected" state where:useAccount()reportsisConnected: trueandstatus: "connected"account.addressisundefinedconnect({ connector: portoConnector })is a no-op — no passkey dialog appears, no error is thrownUsers get stuck in a state where the app thinks they're connected but they can't perform any wallet actions.
Steps to Reproduce
disconnect()(e.g., user clicks logout)useAccount()cycles through these states:connect({ connector: portoConnector })again does nothing — no dialog, no errorExpected Behavior
After
disconnect()+ page reload, either:isConnected: falseso the app can show a clean login flowWhat I See in Storage
After the ghost state occurs:
wagmi.recentConnectorIdstill set to"xyz.ithaca.porto"in localStoragewagmi.storein localStorage hasconnectionsMap with emptyvalue: []portodatabase,storeobject store) still exists with aporto.storeentry containing{state: Object, version: 5}Manually deleting the Porto IndexedDB + wagmi localStorage keys and reloading fixes it.
Possible Root Cause
Looking at Porto's source, I suspect a persistence timing issue:
wallet_disconnectinprovider.tscallsstore.setState((x) => ({ ...x, accounts: [] }))— this updates memory, but the zustand persist write to IndexedDB is async. If the page unloads before the write completes, stale account data survives in IndexedDB.waitForHydrationinstore.tshas asetTimeout(() => resolve(true), 100)fallback. If IndexedDB hydration is slower than 100ms (common on mobile/cold start), the provider may initially read empty state, then hydration completes later with stale accounts, firing a lateconnectevent that creates the ghost state after wagmi already decided "not authorized."The wagmi connector's
connect()withisReconnecting: truereturns{ accounts: [], chainId }instead of failing when no accounts are found — wagmi stores this as a "connected" connection with zero accounts.Workaround
We currently work around this by:
account.isConnected && !account.address) before callingconnect(), and callingdisconnectAsync()firstindexedDB.deleteDatabase('porto')) during logoutwagmi.storeandwagmi.recentConnectorIdfrom localStorage during logoutEnvironment
id.porto.sh