FuelLabs/fuels-ts · error · FuelError

INVALID_PASSWORD

INVALID_PASSWORD

Error message

Failed to decrypt the keystore wallet, the provided password is incorrect.

What it means

Thrown by decryptKeystoreWallet() when the MAC verification fails. After deriving the scrypt key from the supplied password and the keystore's salt, the code computes Keccak-256 over the second half of the key concatenated with the ciphertext and compares it to the stored 'mac'. A mismatch proves the password is wrong (or the keystore is corrupted) — decryption is aborted before any private key is exposed.

Source

Thrown at packages/account/src/wallet/keystore-wallet.ts:151

  const key = scrypt({
    password: passwordBuffer,
    salt: saltBuffer,
    n,
    p,
    r,
    dklen,
  });

  // Verify the MAC. It should be the Keccak-256 hash of the concatenation of the second half of the derived key and the ciphertext.
  const data = Uint8Array.from([...key.subarray(16, 32), ...ciphertextBuffer]);

  const macHashUint8Array = keccak256(data);

  const macHash = stringFromBuffer(macHashUint8Array, 'hex');

  if (mac !== macHash) {
    throw new FuelError(
      ErrorCode.INVALID_PASSWORD,
      'Failed to decrypt the keystore wallet, the provided password is incorrect.'
    );
  }

  // Decrypt the private key.
  const buffer = await decryptJsonWalletData(ciphertextBuffer, key, ivBuffer);

  const privateKey = hexlify(buffer);

  return privateKey;
}

View on GitHub (pinned to b3f37c91ac)

Solutions

  1. Re-enter the password carefully, watching for trailing spaces or autocorrect.
  2. If the password is forgotten, the keystore is unrecoverable — restore from a backup or seed phrase.
  3. Verify the keystore JSON is intact (valid JSON, all crypto fields present, not truncated).
  4. Confirm the keystore was produced by this SDK's encryptKeystoreWallet (same scrypt/AES-128-CTR scheme).
  5. Strip accidental whitespace/newlines from the password string before passing it in.

Example fix

// before
const wallet = await WalletUnlocked.loadKeystore(path, 'wrong-password');
// after
const password = userInput.trim();
const wallet = await WalletUnlocked.loadKeystore(path, password);
Defensive patterns

Strategy: try-catch

Try / catch

try {
  return await decryptKeystoreWallet(json, password);
} catch (err) {
  if (err instanceof FuelError && err.code === ErrorCode.INVALID_PASSWORD) {
    // prompt user for password again; do not expose whether mac vs ciphertext failed
  }
  throw err;
}

Prevention

When it happens

Trigger: Calling decryptKeystoreWallet(jsonWallet, password) — directly or via Wallet.fromKeystoreWallet / WalletUnlocked.loadKeystore — with a password that does not match the one used in encryptKeystoreWallet. Also if the keystore JSON was tampered with (ciphertext, salt, or mac altered).

Common situations: Wrong password typed by the user; password changed but the old keystore file was retained; keystore file corrupted on disk or truncated during copy; cross-tool import where a different KDF/cipher was assumed; trailing whitespace in the password input.

Related errors


AI-assisted analysis of FuelLabs/fuels-ts@b3f37c91ac (2026-08-12). Data as JSON: /api/errors/86f49d80299185fe. Report an issue: GitHub.