nautechsystems/nautilus_trader · error · anyhow::Error

Failed to sign transaction: {e}

Error message

Failed to sign transaction: {e}

What it means

DydxWallet::sign wraps cosmrs tx::SignDoc::sign, which produces the ECDSA/secp256k1 signature over the transaction SignDoc. Any failure inside the signing key operation (malformed doc encoding, key state issue) is surfaced as this error.

Source

Thrown at crates/adapters/dydx/src/execution/wallet.rs:185

            .finish()
    }
}

impl Account {
    /// Get the public key associated with this account.
    #[must_use]
    pub fn public_key(&self) -> PublicKey {
        self.key.public_key()
    }

    /// Sign a [`SignDoc`](tx::SignDoc) with the private key.
    ///
    /// # Errors
    ///
    /// Returns an error if signing fails.
    pub fn sign(&self, doc: tx::SignDoc) -> Result<tx::Raw, anyhow::Error> {
        doc.sign(&self.key)
            .map_err(|e| anyhow::anyhow!("Failed to sign transaction: {e}"))
    }

    /// Update account and sequence numbers from on-chain data.
    pub fn set_account_info(&mut self, account_number: u64, sequence_number: u64) {
        self.account_number = account_number;
        self.sequence_number = sequence_number;
    }

    /// Increment the sequence number (used after successful transaction broadcast).
    pub fn increment_sequence(&mut self) {
        self.sequence_number += 1;
    }

    /// Derive a subaccount for this account.
    ///
    /// # Errors
    ///
    /// Returns an error if the subaccount number is invalid.

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Refresh account_number and sequence from the chain (via the node's auth/abci_query endpoint) and call set_account_info before signing.
  2. Re-create the wallet with DydxWallet::from_private_key to guarantee a valid signing key.
  3. Check the cosmrs version matches what the adapter expects and rebuild the SignDoc with its current API.
  4. Inspect the inner error message ({e}) for the concrete k256/cosmrs cause and fix accordingly.

Example fix

// before: signing with stale sequence
// let raw = wallet.sign(doc)?;
// after: refresh chain state first
wallet.set_account_info(account_number, fresh_sequence);
let raw = wallet.sign(doc)?;
Defensive patterns

Strategy: try-catch

Validate before calling

// refresh chain state before signing
wallet.set_account_info(fetch_account_number()?, fetch_sequence()?);

Try / catch

let raw = match wallet.sign(doc) {
    Ok(r) => r,
    Err(e) => {
        // refresh account/sequence from node and retry once
        wallet.set_account_info(acc_num, seq);
        wallet.sign(doc)?
    }
};

Prevention

When it happens

Trigger: Calling build_transaction (which calls sign) when doc.sign(&self.key) returns Err — typically because the SignDoc was constructed with an account_number/sequence that does not match chain state, or an internal k256 signing failure.

Common situations: Stale account_number/sequence passed to set_account_info before building the tx causing SignDoc mismatch; a wallet whose key was reconstructed incorrectly; cosmrs version incompatibility producing a doc the signer rejects.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08). Data as JSON: /api/errors/90ade20582996b09. Report an issue: GitHub.