{"record":{"id":"47bcf9fc3efe0186","repo":"nautechsystems/nautilus_trader","slug":"venue-venue-str-is-not-a-dex-venue-expected-f","errorCode":null,"errorMessage":"Venue '{venue_str}' is not a DEX venue (expected format 'Chain:DexId')","messagePattern":"Venue '(.+?)' is not a DEX venue \\(expected format 'Chain:DexId'\\)","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/model/src/identifiers/venue.rs","lineNumber":152,"sourceCode":"    #[cfg(feature = \"defi\")]\n    #[must_use]\n    pub fn is_dex(&self) -> bool {\n        self.0.contains(':')\n    }\n\n    #[cfg(feature = \"defi\")]\n    /// Parses a venue string to extract blockchain and DEX type information.\n    ///\n    /// # Errors\n    ///\n    /// Returns an error if:\n    /// - The venue string is not in the format \"chain:dex\"\n    /// - The chain name is not recognized\n    /// - The DEX name is not recognized\n    pub fn parse_dex(&self) -> anyhow::Result<(Blockchain, DexType)> {\n        let venue_str = self.as_str();\n        let Some((chain_name, dex_id)) = venue_str.split_once(':') else {\n            anyhow::bail!(\"Venue '{venue_str}' is not a DEX venue (expected format 'Chain:DexId')\")\n        };\n\n        let chain = Chain::from_chain_name(chain_name).ok_or_else(|| {\n            anyhow::anyhow!(\"Invalid chain '{chain_name}' in venue '{venue_str}'\")\n        })?;\n        let dex_type = DexType::from_dex_name(dex_id)\n            .ok_or_else(|| anyhow::anyhow!(\"Invalid DEX '{dex_id}' in venue '{venue_str}'\"))?;\n\n        Ok((chain.name, dex_type))\n    }\n}\n\nimpl Debug for Venue {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        write!(f, \"\\\"{}\\\"\", self.0)\n    }\n}\n","sourceCodeStart":134,"sourceCodeEnd":170,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/model/src/identifiers/venue.rs#L134-L170","documentation":"Venue::parse_dex parses a venue identifier like \"Ethereum:UniswapV3\" into a (Blockchain, DexType) pair and bails when the string has no ':' separator, i.e. it is not in the 'Chain:DexId' DEX venue format. This only validates the format; unknown chain or DEX names raise separate errors afterwards.","triggerScenarios":"Calling venue.parse_dex() on a venue constructed from a plain string such as \"BINANCE\" or \"Uniswap\" that lacks the Chain:DexId form.","commonSituations":"Config files specifying CEX-style venue names for DEX strategies, hardcoded venue strings missing the colon, or venue parsed from user input without format checks.","solutions":["Format the venue string as 'Chain:DexId', e.g. \"Ethereum:UniswapV3\".","Check the venue's origin — CEX venues legitimately have no DEX form; gate parse_dex calls on the venue actually being a DEX venue.","Validate the string with split_once(':') before constructing the Venue or calling parse_dex."],"exampleFix":"// before\nlet venue = Venue::from(\"UniswapV3\");\nlet (chain, dex) = venue.parse_dex()?;\n// after\nlet venue = Venue::from(\"Ethereum:UniswapV3\");\nlet (chain, dex) = venue.parse_dex()?;","handlingStrategy":"type-guard","validationCode":"fn is_dex_venue(s: &str) -> bool { s.split_once(':').is_some() }","typeGuard":"fn parse_dex_venue(s: &str) -> Option<Venue> {\n    s.split_once(':')?;\n    Some(Venue::from(s))\n}","tryCatchPattern":"match venue.parse_dex() {\n    Ok((chain, dex)) => { /* ... */ }\n    Err(e) => { /* venue is not Chain:DexId — skip or log */ }\n}","preventionTips":["Always construct DEX venues from the 'Chain:DexId' constant rather than free-form strings.","Keep CEX and DEX venue handling in separate code paths."],"tags":["venue","parsing","format"],"backgroundTag":"invalid-argument-format","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"}