FuelLabs/fuels-ts · error · FuelError

HD_WALLET_ERROR

HD_WALLET_ERROR

Error message

invalid path - ${path}

What it means

Thrown by parsePath when a BIP-32 derivation path is malformed: either it has no components after splitting on '/', or it begins with 'm' at a non-zero depth (you cannot re-anchor an already-derived wallet). HDWallet.derivePath uses this to convert a string path into numeric child indices. The path must follow the m/44'/117'/0'/0/0 convention.

Source

Thrown at packages/account/src/hdwallet/hdwallet.ts:45

  }
  return testnet ? TestnetPRV : MainnetPRV;
}

function isPublicExtendedKey(extendedKey: Uint8Array) {
  return [MainnetPUB, TestnetPUB].includes(hexlify(extendedKey.slice(0, 4)));
}

function isValidExtendedKey(extendedKey: Uint8Array) {
  return [MainnetPRV, TestnetPRV, MainnetPUB, TestnetPUB].includes(
    hexlify(extendedKey.slice(0, 4))
  );
}

function parsePath(path: string, depth: number = 0) {
  const components = path.split('/');

  if (components.length === 0 || (components[0] === 'm' && depth !== 0)) {
    throw new FuelError(ErrorCode.HD_WALLET_ERROR, `invalid path - ${path}`);
  }

  if (components[0] === 'm') {
    components.shift();
  }

  return components.map((p) =>
    ~p.indexOf(`'`) ? parseInt(p, 10) + HARDENED_INDEX : parseInt(p, 10)
  );
}

type HDWalletConfig = {
  privateKey?: BytesLike;
  publicKey?: BytesLike;
  chainCode: BytesLike;
  depth?: number;
  index?: number;
  parentFingerprint?: string;

View on GitHub (pinned to b3f37c91ac)

Solutions

  1. Use absolute paths only on a master (depth 0) HDWallet from fromSeed/fromExtendedKey; on children, use relative paths without the 'm' prefix.
  2. Validate the path format before calling derivePath: /^m(\/[0-9]+'?)+$/ for a master wallet.
  3. Keep a reference to the master wallet and derive fresh from it rather than chaining off arbitrary nodes.

Example fix

// before
const child = master.derivePath("m/44'/117'/0'");
child.derivePath("m/0/0"); // 'm' at depth > 0

// after
const child = master.derivePath("m/44'/117'/0'");
child.derivePath("0/0"); // relative path
Defensive patterns

Strategy: validation

Validate before calling

// Validate a BIP-32 path before deriving
function isValidPath(path: string, isMaster: boolean): boolean {
  if (!path) return false;
  const re = isMaster ? /^(m)(\/[0-9]+['\h]?)*$/ : /^([0-9]+['\h]?)(\/[0-9]+['\h]?)*$/;
  return re.test(path);
}

if (isValidPath(path, master.depth === 0)) master.derivePath(path);

Type guard

function isAbsolutePath(path: string): boolean {
  return path.startsWith('m');
}

Try / catch

try {
  child.derivePath(path);
} catch (e) {
  if (e instanceof FuelError && e.code === ErrorCode.HD_WALLET_ERROR && /invalid path/.test(e.message)) {
    // strip leading 'm' for child wallets, or re-derive from master
  } else throw e;
}

Prevention

When it happens

Trigger: Calling hdwallet.derivePath('') (empty), hdwallet.derivePath('m/...') on a wallet whose depth is already > 0 (re-deriving from 'm' on a child), or a path like '//0/0' that splits to empty segments.

Common situations: Reusing an already-derived HDWallet and calling derivePath with an absolute 'm/...' path, passing a user-typed path with stray slashes, or building a path string incorrectly (concatenation bugs).

Related errors


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