{"record":{"id":"004219c71f30b042","repo":"nautechsystems/nautilus_trader","slug":"pool-identifier-must-start-with-0x-was-value","errorCode":null,"errorMessage":"Pool identifier must start with '0x', was: {value}","messagePattern":"Pool identifier must start with '0x', was: (.+?)","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/model/src/defi/pool_identifier.rs","lineNumber":69,"sourceCode":"impl PoolIdentifier {\n    /// Creates a new [`PoolIdentifier`] instance with correctness checking.\n    ///\n    /// Automatically detects variant based on string length:\n    /// - 42 characters (0x + 40 hex): Address variant\n    /// - 66 characters (0x + 64 hex): `PoolId` variant\n    ///\n    /// # Errors\n    ///\n    /// Returns an error if:\n    /// - String doesn't start with \"0x\"\n    /// - Length is neither 42 nor 66 characters\n    /// - Contains invalid hex characters\n    /// - Address checksum validation fails (for Address variant)\n    pub fn new_checked<T: AsRef<str>>(value: T) -> anyhow::Result<Self> {\n        let value = value.as_ref();\n\n        if !value.starts_with(\"0x\") {\n            anyhow::bail!(\"Pool identifier must start with '0x', was: {value}\");\n        }\n\n        match value.len() {\n            42 => {\n                validate_hex_string(value)?;\n\n                // Parse without strict checksum validation, then normalize to checksummed format\n                let addr = value\n                    .parse::<Address>()\n                    .map_err(|e| anyhow::anyhow!(\"Invalid address: {e}\"))?;\n\n                // Store the checksummed version\n                Ok(Self::Address(Ustr::from(addr.to_checksum(None).as_str())))\n            }\n            66 => {\n                // PoolId variant (32 bytes)\n                validate_hex_string(value)?;\n","sourceCodeStart":51,"sourceCodeEnd":87,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/model/src/defi/pool_identifier.rs#L51-L87","documentation":"`PoolIdentifier::new_checked` parses a string into a pool identifier and first requires the canonical `0x` hex prefix. Any input lacking the prefix is rejected with this message, which echoes the offending value. This is a strict-validation constructor: it exists precisely so malformed identifiers fail loudly instead of being silently accepted.","triggerScenarios":"Calling `PoolIdentifier::new_checked` with strings like `abc123...`, bare hex without `0x`, checksummed-but-unprefixed addresses, or identifiers sourced from configs/logs that strip the prefix.","commonSituations":"Loading pool addresses from CSV/config where a tool stripped `0x`; hand-typing an address; interop with systems that represent addresses without the EIP-55/`0x` convention; mixing `new` (lenient) and `new_checked` (strict) expectations.","solutions":["Normalize the input to include the `0x` prefix before constructing: if it doesn't start with `0x`, prepend it.","Validate the string shape (prefix, length 42 for addresses, hex charset) at the ingestion boundary.","Ensure the data source preserves the canonical `0x`-prefixed form (fix exporters/scripts that strip it).","Use the lenient constructor only if unprefixed input is genuinely acceptable in your context."],"exampleFix":"// before\nlet id = PoolIdentifier::new_checked(raw_addr)?;\n// after\nlet normalized = if raw_addr.starts_with(\"0x\") {\n    raw_addr.to_string()\n} else {\n    format!(\"0x{raw_addr}\")\n};\nlet id = PoolIdentifier::new_checked(&normalized)?;","handlingStrategy":"validation","validationCode":"fn has_hex_prefix(s: &str) -> bool {\n    s.starts_with(\"0x\") && s.len() > 2\n}\n// call PoolIdentifier::new_checked only after has_hex_prefix passes","typeGuard":null,"tryCatchPattern":"match PoolIdentifier::new_checked(value) {\n    Ok(id) => id,\n    Err(e) if e.to_string().contains(\"must start with '0x'\") => {\n        let fixed = format!(\"0x{}\", value.trim_start_matches(\"0x\"));\n        PoolIdentifier::new_checked(&fixed)?\n    },\n    Err(e) => return Err(e),\n}","preventionTips":["Normalize addresses to `0x`-prefixed form at the data-ingestion boundary.","Fix upstream exporters/scripts that strip the `0x` prefix from pool addresses.","Validate identifier shape (prefix + length + hex charset) when loading config/CSV data.","Prefer strict constructors like new_checked early so bad data fails at load, not at use."],"tags":["validation","defi","identifier","format"],"backgroundTag":"invalid-identifier-format","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}