nautechsystems/nautilus_trader · error · anyhow::Error
Failed to create signing key: {e}
Error message
Failed to create signing key: {e} What it means
Because SigningKey does not implement Clone, account_offline re-creates the secp256k1 signing key from the wallet's stored private key bytes each time it needs a cosmos Account. This error is returned if that reconstruction fails, meaning the stored bytes are no longer (or never were) a valid key scalar.
Source
Thrown at crates/adapters/dydx/src/execution/wallet.rs:122
private_key_bytes: key_bytes.into_boxed_slice(),
address,
account_id,
})
}
/// Get a dYdX account with zero account and sequence numbers.
///
/// Creates an account using the pre-computed address/account_id.
/// SigningKey is recreated from stored bytes (it doesn't implement Clone).
/// Account and sequence numbers must be set before signing.
///
/// # Errors
///
/// Returns an error if the signing key creation fails.
pub fn account_offline(&self) -> Result<Account, anyhow::Error> {
// SigningKey doesn't impl Clone, so recreate from stored bytes
let key = SigningKey::from_slice(&self.private_key_bytes)
.map_err(|e| anyhow::anyhow!("Failed to create signing key: {e}"))?;
Ok(Account {
address: self.address.clone(),
account_id: self.account_id.clone(),
key,
account_number: 0,
sequence_number: 0,
})
}
/// Returns the pre-computed wallet address.
#[must_use]
pub fn address(&self) -> &str {
&self.address
}
}
/// Represents a dYdX account.View on GitHub (pinned to 18893faf8b)
Solutions
- Re-create the wallet via DydxWallet::from_private_key with the original hex key instead of reconstructing it manually.
- Verify the stored private_key_bytes are exactly 32 bytes and within the valid secp256k1 range.
- If persisted state is corrupted, re-export the key from its source and rebuild the wallet.
- Ensure any serialization/deserialization of the wallet does not alter the key bytes (e.g. base64 vs hex confusion).
Example fix
// before: hand-built wallet with dummy bytes
// let wallet = DydxWallet { private_key_bytes: vec![0u8; 16].into_boxed_slice(), ... };
// let acct = wallet.account_offline()?; // fails
// after
let wallet = DydxWallet::from_private_key(&hex_key)?;
let acct = wallet.account_offline()?; Defensive patterns
Strategy: validation
Validate before calling
assert_eq!(wallet_key_bytes.len(), 32, "stored key must be 32 bytes");
Try / catch
let account = wallet.account_offline()
.map_err(|e| {
log::error!("signing key reconstruction failed: {e}; rebuild wallet from hex key");
e
})?; Prevention
- Only construct wallets via DydxWallet::from_private_key
- Avoid serializing/deserializing wallet internals; persist the hex key and rebuild
- Recreate the wallet if key bytes may have been corrupted in state
When it happens
Trigger: Calling DydxWallet::account_offline when SigningKey::from_slice(&self.private_key_bytes) fails — corrupted or wrongly-sized private_key_bytes, or a wallet constructed through a path that skipped key validation.
Common situations: Deserializing a wallet from a snapshot/state file whose key bytes were truncated or corrupted; manually constructing the struct in tests with dummy bytes; memory corruption is rare — usually the stored bytes were never a valid 32-byte scalar.
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
- Invalid secp256k1 private key: {e}
- Signer private key in '{}' is not a valid secp256k1 private
- Failed to sign: {e}
- Failed to derive account ID: {e}
- Failed to sign transaction: {e}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/6d1545f05291e4b4.
Report an issue: GitHub.