Wallet Troubleshooting
Find your symptom, read the cause, apply the fix.
Passkeys
Tapping the passkey option does nothing
The WebAuthn Relying Party ID for wallet passkeys is pinned into the build from
VITE_WEBAUTHN_RP_ID and is never derived from the host serving the page. If that pinned value is
not a registrable domain suffix of the origin you are on, the browser rejects the ceremony with a
SecurityError before the operating system shows anything. No Face ID sheet, no Touch ID
prompt, no Windows Hello dialog, no error dialog.
| Where you are | Correct VITE_WEBAUTHN_RP_ID | Passkeys work? |
|---|---|---|
superhero.com (production) | superhero.com, the default | Yes |
Local dev on localhost | localhost | Yes, if set |
| Any other origin | A registrable suffix of that origin | Only if set for that build |
Fix: on production, report it. On any other origin, rebuild with the right
VITE_WEBAUTHN_RP_ID, or use a recovery phrase instead.
The app catches this exception and shows "Passkeys aren't available on this domain (this build expects …). Use a recovery phrase instead." The name it prints is the RP ID the build was compiled with. The DOM exception name and message are also written to the browser console; include them in any report.
The passkey prompt appeared, then the wallet did not open
The ceremony ran but the derived key did not unwrap this vault, so the unlock failed closed. Two common causes:
- You picked the wrong passkey from the OS list. Retry and choose the Superhero one.
- The credential was rekeyed by the platform. Apple has a known passkey-rekey issue that can invalidate a previously stable PRF output. This is why the recovery code exists as a passkey-independent factor.
Fix: unlock with your recovery code or passphrase instead, on the same device. Both are offered on the "this device already has a wallet" screen.
Tapping the passkey card opens an onboarding screen instead of a biometric prompt
Your device has a wallet, but that wallet has no passkey factor; it unlocks with a passphrase and recovery code. The card hands off to the wallet screen, where your passphrase opens it. You can enroll a device passkey from there.
It says "Tap to try again" with no error
You cancelled, or the OS dismissed the sheet. Nothing is logged as an error. Tap again.
Connecting an external wallet
The wallet is not detected
Superhero scans for an injected wallet over a browser message connection with a short window:
| Situation | Detection window |
|---|---|
| Desktop browser, user-initiated connect | 4 seconds |
| Mobile or Safari, not framed | 100 ms, failing fast to the deep-link path |
| Silent reconnect after a page refresh | 15 seconds |
The reconnect window is longer because the extension's content script can be injected after the app has already booted.
Fix: confirm the extension is installed and enabled for this site, unlock it, then reload the
page and use Connect again. If no wallet answers and the page is not framed, the app falls back to
a deep link: superhero:// on mobile, otherwise wallet.superhero.com in a new window.
The app opened wallet.superhero.com instead of my extension
That is the fallback firing: no extension answered within the detection window. See above.
After a refresh the app shows my address but cannot sign
You have a restored static (read-only) account rather than a live RPC session. Account subscription and address-change events only exist over a live connection.
Fix: click Connect again to re-establish the RPC session. Silent reconnection is attempted once per page load, but only when both a previously active account and persisted wallet info exist.
The app spontaneously shows "disconnected" while the extension is open
A health check runs every five seconds and clears connection state when the SDK reports no accounts. A stale connection is treated as no connection. Reconnect.
Disconnect did not stick; it reconnected on refresh
Disconnecting clears the persisted session keys (account:activeAccount, wallet:walletInfo,
wallet:balance, dex:recentActivities, liquidityPositions), stops wallet detection and drops
the cached connection. If a reconnect still happens, check for a stale ?address= query parameter
in the URL. The app consumes that parameter to install a static account, then strips it.
Hardware accounts in Superhero Wallet
There is no "Add Ledger accounts" button
It is hidden, not missing. The button appears only when the account protocol is æternity and the surface is neither Firefox nor a mobile app:
| Surface | Ledger button |
|---|---|
| Chrome, Brave, Opera extension | Shown |
wallet.superhero.com in a Chromium browser | Shown |
| Firefox (extension or web) | Hidden; Firefox does not implement WebUSB |
| iOS or Android app | Hidden |
| A non-æternity account selected | Hidden |
Fix: use a Chromium browser, or switch to an æternity account first. AirGap has none of these restrictions.
"Connection timed out" when importing from a Ledger
Two causes: the device is not properly plugged in, or the æternity app is not open on it. Plug in over USB, open the æternity app, then press connect. The same applies when signing: the device must be unlocked with the æternity app active.
An AirGap QR code will not scan or decode
Set AirGap Vault to QR code V3. A V2 payload will not deserialize. Every AirGap screen also
accepts the airgap-wallet://?ur=… string pasted by hand, which is the way through if the camera
is the problem.
An AirGap account will not sign a message
It cannot. Superhero Wallet shows "Signing messages is currently not supported for AirGap accounts" and stops. Transactions are supported; messages are not. If an æpp needs a message signature, use a non-AirGap account for it.
Network
The wallet is on a different network from the app
Superhero builds are network-pinned at build time through VITE_NETWORK. The app offers only
the network its bundle was built for; there is no in-app network switcher.
Fix: switch networks in your wallet to match the build: ae_mainnet on superhero.com. For
testnet work, use a testnet build and see Using Testnet.
Balances and signing
"Insufficient balance" when the balance looks sufficient
On a token trade, the Max button does not offer your whole balance. It withholds a slippage allowance plus a flat gas reserve:
max = balance − balance × (slippage + 1) / 100 − 0.001 AEWith the default 1% slippage that is a 2% reserve plus 0.001 AE. Separately, gas is charged on top of the transaction fee, up to the gas limit, which is why the signing prompt shows a "Gas, at most" row as well as "Network fee". A balance that exactly covers the amount will not cover the amount plus fee plus gas.
Fix: leave headroom, or lower the amount. Do not lower slippage to free up funds; that just makes the trade fail differently.
The signing prompt refuses to let me approve
By design. If the transaction envelope, a contract call's arguments, or a wrapped inner transaction cannot be decoded, the confirmation fails closed and approval is not offered. There is no "show raw bytes and sign anyway".
Fix: do not try to work around it. Report what you were doing when it appeared.
"no unlock prompt is mounted — refusing to sign"
The in-page signer asked for user verification and found no prompt host mounted, so it rejected immediately rather than hanging. This is the fail-closed guard, not a crash.
Fix: reload the page and retry the action. If it recurs reproducibly, report it with the exact action.
"derived key does not match the expected account address — refusing to sign"
The signer derived a key that does not produce the address it was installed for, and refused. The device's wallet changed underneath a live session (a restore or import replaced it), or an address and index pair drifted apart.
Fix: reload the page so the account list is rebuilt from the current vault, then retry.
Storage and the built-in wallet
My built-in wallet disappeared
The encrypted vault lives in this browser's IndexedDB for this origin. Clearing site data deletes it, and Safari's Intelligent Tracking Prevention can evict it after roughly seven days without interaction.
Neither your passphrase nor your recovery code can bring it back, because both need the deleted record to unwrap anything. What survives is the written recovery phrase, or a syncing passkey if the wallet was created by the passkey path. The full matrix is in The Built-In Wallet.
My wallet unlocks but the app does not know my address
The address list in localStorage was cleared while the encrypted vault in IndexedDB survived. This is a
normal outcome of some "clear site data" variants.
Fix: open the wallet screen and unlock once; addresses are re-derived from index 0 upward and the list is rebuilt.
Restoring from a passkey shows an address I do not recognise
The restore screen checks the derived address for on-chain activity before saving anything. If it says the account has no on-chain activity, you very likely picked a passkey that belongs to a seed-phrase wallet, which derives a valid but completely empty different wallet.
Fix: do not confirm. Go back and import your recovery phrase (installed app), or connect your existing wallet instead. Confirming would persist the wrong wallet and then block the correct import with "a vault already exists".
There is no "Import an existing wallet" option
Importing a seed phrase or private key is offered only in the installed app (Add to Home Screen / installed PWA). In a plain browser tab, "I already have a wallet" means Connect, which never asks for your secret.
Nothing persists at all (private browsing)
In Safari private mode and with site data blocked, storage reads can fail. The app treats an unreadable address list as "no wallet on this device" and an unreadable vault probe as unknown rather than claiming you have no wallet.
Fix: use a normal window for anything you intend to keep.
Reporting a bug
| What | Where |
|---|---|
| App, mobile app or PWA bug | github.com/superhero-com/superhero/issues (opens in a new tab), the same destination as the in-app "Send Feedback" button |
| API, indexer or a wrong figure in a response | github.com/superhero-com/superhero-api/issues (opens in a new tab) |
| Superhero Wallet (extension, app, web wallet) bug | The wallet's own Report a bug entry, at form.typeform.com/to/Kk3Zyjdr (opens in a new tab), or github.com/superhero-com/superhero-wallet/issues (opens in a new tab) |
| Security report, legal, privacy or data protection | superherowallet@protonmail.com |
| Chat | chat.superhero.com |
Include in any report:
- the token name or page you were on,
- your
ak_...address, - the transaction hash if one was produced,
- what you expected and what happened,
- for a Superhero Wallet bug, the software version and commit from the wallet's More → About screen, which also shows the node and middleware versions it is talking to,
- for passkey problems, the DOM exception name from the browser console and the exact on-screen message.
Never include a private key, a seed phrase, or a screenshot showing either.
Related
- The Built-In Wallet: the vault, factor and storage model these symptoms come from.
- Connecting a Wallet: the detection and handshake the connection failures happen inside.
- Backup & Recovery: what to do before any of this bites.
- Using Testnet: the network-pinning that causes mismatch symptoms.
- Support: every reporting route in one place.