{"record":{"id":"01c5f95ed869ed71","repo":"nautechsystems/nautilus_trader","slug":"historical-open-interest-request-requires-period","errorCode":null,"errorMessage":"historical open interest request requires `period` metadata","messagePattern":"historical open interest request requires `period` metadata","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/binance/src/futures/data.rs","lineNumber":492,"sourceCode":"            .filter(|value| !value.is_empty())\n        else {\n            anyhow::bail!(\"custom data request requires `instrument_id` metadata\");\n        };\n\n        InstrumentId::from_str(raw_instrument_id)\n            .with_context(|| format!(\"invalid instrument_id metadata `{raw_instrument_id}`\"))\n    }\n\n    fn required_period_metadata(data_type: &DataType) -> anyhow::Result<String> {\n        let Some(period) = data_type\n            .metadata()\n            .as_ref()\n            .and_then(|m| m.get(\"period\"))\n            .and_then(|v| v.as_str())\n            .map(str::trim)\n            .filter(|value| !value.is_empty())\n        else {\n            anyhow::bail!(\"historical open interest request requires `period` metadata\");\n        };\n\n        Ok(period.to_string())\n    }\n\n    fn coinm_open_interest_hist_params(\n        http: &BinanceFuturesHttpClient,\n        instrument_id: &InstrumentId,\n    ) -> anyhow::Result<(String, String)> {\n        let symbol = format_binance_symbol(instrument_id);\n        if let Some(pair) = symbol.strip_suffix(\"_PERP\") {\n            return Ok((pair.to_string(), \"PERPETUAL\".to_string()));\n        }\n\n        let definition = http\n            .instrument_metadata(*instrument_id)\n            .with_context(|| format!(\"missing COIN-M definition for {instrument_id}\"))?;\n        let BinanceFuturesInstrument::CoinM(definition) = definition else {","sourceCodeStart":474,"sourceCodeEnd":510,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/binance/src/futures/data.rs#L474-L510","documentation":"Historical open interest custom data requests (BinanceFuturesOpenInterestHist) additionally require a `period` metadata string (the Binance OI stats period such as '5m', '1h'). `required_period_metadata` bails when it is missing or blank.","triggerScenarios":"request_data on data type BinanceFuturesOpenInterestHist where metadata lacks a `period` key, has a non-string value, or an empty/whitespace value.","commonSituations":"Constructing the OpenInterestHist DataCmd without period metadata, or copying a snippet for spot open interest (which has no period) and reusing it for futures hist.","solutions":["Add `period` to the request metadata with a Binance-supported period (e.g. \"5m\",\"15m\",\"30m\",\"1h\",\"2h\",\"4h\",\"6h\",\"12h\",\"1d\")","Verify the value is serialized as a string, not a number or null","Trim whitespace in configuration","Check Binance futures API docs for currently accepted periods if the request is rejected after adding one"],"exampleFix":"// before\nIndexMap::from([(\"instrument_id\".to_string(), json!(\"BTCUSDT-PERP.BINANCE\"))])\n// after\nIndexMap::from([\n  (\"instrument_id\".to_string(), json!(\"BTCUSDT-PERP.BINANCE\")),\n  (\"period\".to_string(), json!(\"5m\")),\n])","handlingStrategy":"validation","validationCode":"const OI_PERIODS: [&str; 9] = [\"5m\",\"15m\",\"30m\",\"1h\",\"2h\",\"4h\",\"6h\",\"12h\",\"1d\"];\nlet period = data_type.metadata().and_then(|m| m.get(\"period\")).and_then(|v| v.as_str());\nassert!(period.map_or(false, |p| OI_PERIODS.contains(&p.trim())), \"period metadata required\");","typeGuard":"fn has_period(meta: &Option<IndexMap<String, serde_json::Value>>) -> bool {\n    meta.as_ref().and_then(|m| m.get(\"period\")).and_then(|v| v.as_str()).map(str::trim).map_or(false, |s| !s.is_empty())\n}","tryCatchPattern":"match client.request_data(data_type).await {\n    Err(e) if e.to_string().contains(\"requires `period` metadata\") => return Err(anyhow::anyhow!(\"add period metadata e.g. '5m'\")),\n    other => other,\n}","preventionTips":["Include period metadata for OpenInterestHist requests","Use a builder that pairs instrument_id and period together","Validate period against Binance's accepted set"],"tags":["rust","metadata","open-interest","binance"],"backgroundTag":"missing-required-argument","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}