Skip to content

mnemonicToSecretKey: unhelpful error when given a 24-word BIP-39 mnemonic (Pera Universal Wallet) #1064

@firedintern

Description

@firedintern

Summary

algosdk.mnemonicToSecretKey() throws a generic failed to decode mnemonic error when given a 24-word BIP-39 mnemonic exported from Pera Wallet's Universal Wallet. There is no indication that the format is wrong or what format is expected.

Steps to Reproduce

  1. Create a new wallet in Pera Wallet (iOS/Android) — the default type is Universal Wallet
  2. Export the passphrase: Settings → Security → Show Passphrase
  3. Copy the 24-word mnemonic
  4. Try to use it with algosdk:

```typescript
import algosdk from "algosdk";
algosdk.mnemonicToSecretKey("word1 word2 ... word24");
// ❌ Error: failed to decode mnemonic
```

Expected Behavior

The error message should indicate the format mismatch clearly, e.g.:

```
Error: failed to decode mnemonic — expected a 25-word Algorand mnemonic, received 24 words.
Pera Universal Wallet exports a BIP-39 24-word mnemonic which is not compatible with algosdk.
Use a legacy Algorand Account in Pera (25 words) or generate one via algosdk.generateAccount().
```

Root Cause

Pera Wallet introduced Universal Wallets (BIP-39 HD standard, 24 words) alongside the legacy Algo25 Wallets (Algorand-native, 25 words + checksum). The two formats are incompatible. algosdk only supports the Algo25 format but gives no indication of this in the error.

Impact

Developers using Pera Wallet (the most popular Algorand wallet) for local development or scripting will hit a silent dead end. The current error message failed to decode mnemonic gives zero actionable guidance — users assume they copied the wrong words, not that the format is fundamentally different.

Workaround

In Pera Wallet, explicitly create a legacy Algorand Account (not a Universal Wallet) to get a 25-word algosdk-compatible mnemonic. Alternatively, generate one directly:

```typescript
const account = algosdk.generateAccount();
const mnemonic = algosdk.secretKeyToMnemonic(account.sk); // always 25 words
```

Suggested Fix

In the mnemonicToSecretKey / seedFromMnemonic function, check the word count before attempting to decode and throw a descriptive error:

```typescript
const words = mnemonic.trim().split(/\s+/);
if (words.length !== 25) {
throw new Error(
`Invalid mnemonic: expected 25 words, got ${words.length}. ` +
`If using Pera Wallet, make sure to export from a legacy Algorand Account, not a Universal Wallet.`
);
}
```

Environment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions