unionlabs/union · error · Error
No wallet available
Error message
No wallet available
What it means
Thrown in the BTCfi Step3 flow (app2) when preparing to sign a Babylon ownership message: the app takes the stored wallet name from cosmosStore.connectedWallet and looks up the injected provider via window[connectedWallet]; if that global is absent, there is no wallet API to call signArbitrary on and the Effect fails synchronously.
Source
Thrown at app2/src/routes/btcfi/step/Step3.svelte:107
}
if (!isEvmAddressValid) {
return
}
const addressToUse = evmAddress.trim()
isLoading = true
const message =
`I verify that I own this Babylon address and want to receive BTCfi rewards on Ethereum address: ${addressToUse}`
runPromise(
pipe(
Effect.sync(() => {
const walletApi = cosmosStore.connectedWallet
&& (window as any)[cosmosStore.connectedWallet]
if (!walletApi) {
throw new Error("No wallet available")
}
return walletApi
}),
Effect.flatMap((walletApi) =>
Effect.tryPromise({
try: () => {
const chainId = "bbn-1"
return walletApi.signArbitrary(chainId, walletAddress, message)
},
catch: (error) => new Error(`Failed to sign message: ${error}`),
})
),
Effect.flatMap((signature) =>
verifyBTCFIWallet({
bbnAddress: walletAddress,
message,
signature: JSON.stringify(signature),
evmAddress: addressToUse,View on GitHub (pinned to 031785bb6d)
Solutions
- Reconnect the wallet (trigger the connect flow again) so connectedWallet matches a currently injected provider
- Verify the extension is installed and enabled for the site, then reload
- Clear stale connection state when window[connectedWallet] is missing instead of attempting to sign
Example fix
// before
const walletApi = cosmosStore.connectedWallet && (window as any)[cosmosStore.connectedWallet]
// after (gate the flow and re-connect on miss)
const walletApi = cosmosStore.connectedWallet && (window as any)[cosmosStore.connectedWallet]
if (!walletApi) {
cosmosStore.connectedWallet = null // clear stale state
await reconnect() // run the wallet-connect flow again
return
} Defensive patterns
Strategy: validation
Validate before calling
const walletName = cosmosStore.connectedWallet
const walletApi = walletName && (window as any)[walletName]
if (!walletApi || typeof walletApi.signArbitrary !== "function") {
cosmosStore.connectedWallet = null // clear stale state
// trigger the connect flow instead of signing
} Type guard
const isInjectedCosmosWallet = (w: unknown): w is { signArbitrary: (chainId: string, signer: string, message: string) => Promise<unknown> } =>
typeof w === "object" && w !== null && typeof (w as any).signArbitrary === "function" Try / catch
try {
// Effect pipeline already routes this via Effect.orElse; for plain code:
await walletApi.signArbitrary("bbn-1", address, message)
} catch (error) {
if ((error as Error).message === "No wallet available") {
// prompt reconnect; do not retry until window global exists
}
throw error
} Prevention
- Verify window[connectedWallet] exists before enabling the sign action
- Clear persisted connection state on page load if the provider global is missing
- Handle wallet injection races (window onload / extension events) before user actions
When it happens
Trigger: cosmosStore.connectedWallet is set (e.g. "keplr" or "leap") but the corresponding window global is missing: extension uninstalled/disabled, injection not finished at call time, the name restored from persisted state after a browser profile change, or a non-cosmos wallet was connected.
Common situations: User disabled the extension between sessions; page loaded and user clicked through before injection (race); localStorage/session persisted connectedWallet stale; mobile in-app browser without the extension.
Related errors
- HTTP ${res.status} - ${res.statusText}
- NOT IMPLEMENTED
- Connector ${evmWalletId} not found
- No Sui account returned by wallet
- Transaction failed: ${transaction?.vm_status} - ${JSON.strin
AI-assisted analysis of unionlabs/union@031785bb6d (2026-08-16).
Data as JSON: /api/errors/c7131e9dec08400f.
Report an issue: GitHub.