{"record":{"id":"110298919f3e3120","repo":"nautechsystems/nautilus_trader","slug":"funding-rates-are-only-available-for-derive-perpet","errorCode":null,"errorMessage":"Funding rates are only available for Derive perpetual instruments (got {instrument_id})","messagePattern":"Funding rates are only available for Derive perpetual instruments \\(got (.+?)\\)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/derive/src/data.rs","lineNumber":1241,"sourceCode":"                params,\n            ));\n\n            if let Err(e) = sender.send(DataEvent::Response(response)) {\n                log::error!(\"Failed to send Derive trades response: {e}\");\n            }\n            Ok(())\n        });\n\n        Ok(())\n    }\n\n    fn request_funding_rates(&self, request: RequestFundingRates) -> anyhow::Result<()> {\n        let instrument_id = request.instrument_id;\n        let instrument = self\n            .instruments\n            .get_cloned(&instrument_id)\n            .ok_or_else(|| InstrumentLookupError::not_found(instrument_id))?;\n        anyhow::ensure!(\n            matches!(instrument, InstrumentAny::CryptoPerpetual(_)),\n            \"Funding rates are only available for Derive perpetual instruments (got {instrument_id})\",\n        );\n        let venue_symbol = format_venue_symbol(&instrument_id)?.to_string();\n\n        let http_client = self.http_client.clone();\n        let sender = self.data_sender.clone();\n        let clock = self.clock;\n        let client_id = request.client_id.unwrap_or(self.client_id);\n        let request_id = request.request_id;\n        let params = request.params;\n        let start = request.start;\n        let end = request.end;\n        let limit = request.limit.map(NonZeroUsize::get);\n        let start_nanos = datetime_to_unix_nanos(start);\n        let end_nanos = datetime_to_unix_nanos(end);\n        let start_ms = start.map(|dt| dt.as_millisecond());\n        let end_ms = end.map(|dt| dt.as_millisecond());","sourceCodeStart":1223,"sourceCodeEnd":1259,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/derive/src/data.rs#L1223-L1259","documentation":"`request_funding_rates` looks up the requested instrument and, via `anyhow::ensure!`, throws when the instrument is not a `CryptoPerpetual`. Derive funding rates are only defined for perpetuals, so requests for spots/options/futures are rejected.","triggerScenarios":"Calling `request_funding_rates` with an `instrument_id` that resolves to a Derive spot, option, or dated-future instrument instead of a perpetual (e.g. \"ETH-20260926-4000-C.DERIVE\").","commonSituations":"Configuring a strategy's funding-rate subscription against an options/dated instrument; automated code that iterates all instruments in the cache and requests funding rates for each; users confusing Derive futures with perpetual swaps.","solutions":["Use a Derive perpetual instrument ID such as `ETH-PERP.DERIVE`.","Check the instrument type before requesting: `matches!(instrument, InstrumentAny::CryptoPerpetual(_))`.","Filter your instrument list to perpetuals before issuing funding-rate requests.","For non-perpetual instruments, remove funding-rate logic or use a data source that supports them."],"exampleFix":"// before\nclient.request_funding_rates(RequestFundingRates::new(\"ETH-20260926-4000-C.DERIVE\", ...))?;\n// after\nclient.request_funding_rates(RequestFundingRates::new(\"ETH-PERP.DERIVE\", ...))?;","handlingStrategy":"validation","validationCode":"// Rust\nif let Some(inst) = cache.instrument(&instrument_id) {\n    if !matches!(inst, InstrumentAny::CryptoPerpetual(_)) {\n        return Err(anyhow!(\"funding rates require a perpetual: {instrument_id}\"));\n    }\n}","typeGuard":"fn is_perp(inst: &InstrumentAny) -> bool {\n    matches!(inst, InstrumentAny::CryptoPerpetual(_))\n}","tryCatchPattern":"if let Err(e) = client.request_funding_rates(req) {\n    if e.to_string().contains(\"perpetual instruments\") {\n        // skip or switch instrument\n    }\n}","preventionTips":["Use `*PERP.DERIVE` instrument IDs for funding-rate requests.","Filter the cache to perpetuals before bulk funding requests.","Check instrument kind in strategy config validation.","Keep options/futures on separate request paths."],"tags":["funding-rates","instrument-type","derive","validation"],"backgroundTag":"unsupported-operation","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}