nautechsystems/nautilus_trader · error · anyhow::Error

Binance Spot SBE market-data streams require an Ed25519 API

Error message

Binance Spot SBE market-data streams require an Ed25519 API key (HMAC keys are not supported): {e}

What it means

The Binance Spot SBE market-data WebSocket client was constructed without Ed25519-compatible credentials. SBE streams require an Ed25519 API key; an HMAC (secret-key) credential or otherwise malformed key material caused `Ed25519Credential::new` to fail, and the underlying error is surfaced via `{e}`.

Source

Thrown at crates/adapters/binance/src/spot/websocket/streams/client.rs:143

    /// # Errors
    ///
    /// Returns an error if credential creation fails.
    pub fn new(
        url: Option<String>,
        api_key: Option<String>,
        api_secret: Option<String>,
        heartbeat: Option<u64>,
        transport_backend: TransportBackend,
    ) -> anyhow::Result<Self> {
        let url = url.unwrap_or(BINANCE_SPOT_SBE_WS_URL.to_string());

        let credential = match (
            api_key.map(SecretString::from),
            api_secret.map(SecretString::from),
        ) {
            (Some(key), Some(secret)) => {
                let credential = Ed25519Credential::new(key, secret).map_err(|e| {
                    anyhow::anyhow!(
                        "Binance Spot SBE market-data streams require an Ed25519 API key \
                         (HMAC keys are not supported): {e}"
                    )
                })?;
                Some(Arc::new(credential))
            }
            _ => None,
        };

        Ok(Self {
            url,
            credential,
            heartbeat,
            signal: Arc::new(AtomicBool::new(false)),
            slots: Arc::new(ConnectionSlots(Mutex::new(Vec::new()))),
            connect_lock: Arc::new(tokio::sync::Mutex::new(())),
            out_tx: Arc::new(Mutex::new(None)),
            out_rx: Arc::new(Mutex::new(None)),

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Create an Ed25519-type API key on Binance (in the API management page choose Ed25519, not HMAC) and supply its public key as the api key and its private key as the secret.
  2. Verify the private key is a valid PEM/base64 Ed25519 key with no trailing whitespace or newlines.
  3. Check the underlying `{e}` message; if it says the key format is invalid, re-encode the key (e.g. ensure PEM headers/footers).
  4. If you cannot use Ed25519 keys, use the non-SBE (JSON) market-data streams, which accept HMAC keys.

Example fix

// before: HMAC key
api_key = "my_hmac_key"; api_secret = "my_hmac_secret";
// after: Ed25519 key created on Binance
api_key = "<ed25519 public key (base64)>"; api_secret = "<ed25519 private key (PEM)>";
Defensive patterns

Strategy: validation

Validate before calling

fn require_ed25519_key(api_key: &str, api_secret: &str) -> Result<(), String> {
    if api_key.is_empty() || api_secret.is_empty() {
        return Err("api key/secret must not be empty".into());
    }
    // Ed25519 private keys are PEM or base64 DER, not HMAC hex secrets
    if api_secret.chars().all(|c| c.is_ascii_hexdigit()) {
        return Err("secret looks like an HMAC key; SBE streams require an Ed25519 key".into());
    }
    Ok(())
}

Try / catch

match Ed25519Credential::new(key, secret) {
    Ok(c) => Ok(Some(Arc::new(c))),
    Err(e) => Err(anyhow::anyhow!(
        "Binance Spot SBE market-data streams require an Ed25519 API key (HMAC keys are not supported): {e}"
    )),
}

Prevention

When it happens

Trigger: Calling `client.new(...)` on the Spot SBE stream client with an HMAC-style API key/secret pair, an empty key, or invalid key material; `Ed25519Credential::new(key, secret)` returns `Err`.

Common situations: Users reusing their classic HMAC Binance API key with the newer SBE endpoint; keys created without Ed25519 signing enabled; a typo'd or truncated key pasted into config.

Related errors


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