nautechsystems/nautilus_trader · error

Lighter funding-rate requests require a perpetual instrument

Error message

Lighter funding-rate requests require a perpetual instrument: {instrument_id}

What it means

Funding-rate requests in the Lighter adapter are only valid for perpetual instruments. The adapter looks up the instrument and asserts it is a CryptoPerpetual before issuing the HTTP funding-rate request; any other instrument type (spot, etc.) is rejected.

Source

Thrown at crates/adapters/lighter/src/data/mod.rs:1697

                Err(e) => {
                    log::error!("Lighter trades request failed for {instrument_id}: {e}");
                }
            }
        });

        Ok(())
    }

    fn request_funding_rates(&self, request: RequestFundingRates) -> anyhow::Result<()> {
        let instrument_id = request.instrument_id;
        log::debug!("Requesting Lighter funding rates for {instrument_id}");

        let instrument = self
            .instruments
            .get_cloned(&instrument_id)
            .ok_or_else(|| InstrumentLookupError::not_found(instrument_id))?;

        anyhow::ensure!(
            matches!(instrument, InstrumentAny::CryptoPerpetual(_)),
            "Lighter funding-rate requests require a perpetual instrument: {instrument_id}",
        );

        let http = self.http_client.clone();
        let sender = self.data_sender.clone();
        let request_id = request.request_id;
        let client_id = request.client_id.unwrap_or(self.client_id);
        let start = request.start;
        let end = request.end;
        let limit = request.limit.map(|n| n.get());
        let start_nanos = datetime_to_unix_nanos(start);
        let end_nanos = datetime_to_unix_nanos(end);
        let params = request.params;
        let clock = self.clock;

        self.spawn_task(async move {
            match http

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Use a perpetual instrument ID (e.g. ending in -PERP) for funding-rate requests.
  2. Verify which instruments were loaded/registered by the client — funding is defined only for perps.
  3. Check your config/instrument catalog so the requested ID maps to a CryptoPerpetual.
  4. If you genuinely need funding-like data for another product, confirm whether the venue even provides it.

Example fix

// before
client.request_funding_rates(RequestFundingRates::new(InstrumentId::from("ETH-USDC.LIGHTER")));
// after
client.request_funding_rates(RequestFundingRates::new(InstrumentId::from("ETH-USDC-PERP.LIGHTER")));
Defensive patterns

Strategy: validation

Validate before calling

if !instrument_id.to_string().ends_with("-PERP") {
    return Err(anyhow!("funding rates require a perpetual instrument: {instrument_id}"));
}

Type guard

fn is_perp(inst: &InstrumentAny) -> bool {
    matches!(inst, InstrumentAny::CryptoPerpetual(_))
}

Try / catch

match client.request_funding_rates(req).await {
    Err(e) if e.to_string().contains("require a perpetual instrument") => {
        log::warn!("skipping funding-rate request for non-perp {id}");
    }
    r => r?,
}

Prevention

When it happens

Trigger: Calling request_funding_rates() with an instrument_id that resolves to a non-perpetual instrument (e.g. a spot instrument), or with an instrument_id registered as something other than InstrumentAny::CryptoPerpetual.

Common situations: Requesting funding rates for a spot pair by mistake; a misconfigured instrument ID that matches a spot market instead of the -PERP market.

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/42f4f1f701699816. Report an issue: GitHub.