nautechsystems/nautilus_trader · error

Lighter execution client cannot update leverage without cred

Error message

Lighter execution client cannot update leverage without credentials

What it means

Updating leverage on Lighter is a signed transaction that requires API credentials (account key). The execution client holds an optional credential; if it was never configured, update_leverage refuses rather than attempting an unsigned request that the venue would reject.

Source

Thrown at crates/adapters/lighter/src/execution.rs:2076

    ///
    /// Nautilus does not expose a `set_leverage` command on the execution
    /// trait, so this method is callable directly from strategy or bootstrap
    /// code.
    ///
    /// # Errors
    ///
    /// Returns an error if credentials are missing, the instrument is not
    /// registered, `initial_margin_fraction` is outside `1..=10_000`, or
    /// the dispatch pre-flight (nonce allocation, signing) fails. Transport
    /// errors after dispatch are logged but not returned synchronously.
    pub fn update_leverage(
        &self,
        instrument_id: InstrumentId,
        initial_margin_fraction: u16,
        margin_mode: LighterPositionMarginMode,
    ) -> anyhow::Result<()> {
        let credential = self.credential.as_ref().ok_or_else(|| {
            anyhow::anyhow!("Lighter execution client cannot update leverage without credentials")
        })?;

        let market_index = self.registry.market_index(&instrument_id).ok_or_else(|| {
            anyhow::anyhow!("no Lighter market_index registered for instrument {instrument_id}")
        })?;

        anyhow::ensure!(
            (1..=10_000).contains(&initial_margin_fraction),
            "initial_margin_fraction must be in 1..=10_000, was {initial_margin_fraction}",
        );

        let ReservedTxContext {
            context,
            mut send_reservation,
        } = self.build_tx_context(credential)?;

        let connection_epoch = send_reservation.connection_epoch;

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Configure the Lighter execution client with API credentials (api key/private key) before calling update_leverage.
  2. Verify the same credential source used for signing orders is wired into this client instance.
  3. Check environment/config (e.g. LIGHTER_API_KEY or equivalent) is present and loaded at client construction.

Example fix

// before
let client = LighterExecutionClient::builder().instrument_provider(provider).build()?;
// after
let client = LighterExecutionClient::builder()
    .instrument_provider(provider)
    .credential(credential) // api key + private key
    .build()?;
Defensive patterns

Strategy: validation

Validate before calling

if client.credential().is_none() {
    return Err("configure Lighter API credentials before update_leverage".into());
}

Try / catch

if let Err(e) = client.update_leverage(iid, imf, mode).await {
    if e.to_string().contains("without credentials") {
        // rebuild client with credentials or surface config error to operator
    }
}

Prevention

When it happens

Trigger: Calling execution_client.update_leverage(instrument_id, initial_margin_fraction, margin_mode) on a client constructed without API key/credential (e.g. market-data-style or read-only configuration).

Common situations: Adapter configured with only a public/signing-less setup; credentials provided to the data client but not the execution client; env vars for the API key missing at startup; key rotation left the client credential=None.

Related errors


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