nautechsystems/nautilus_trader · error · anyhow::Error
Pool identifier must start with '0x', was: {value}
Error message
Pool identifier must start with '0x', was: {value} What it means
`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.
Source
Thrown at crates/model/src/defi/pool_identifier.rs:69
impl PoolIdentifier {
/// Creates a new [`PoolIdentifier`] instance with correctness checking.
///
/// Automatically detects variant based on string length:
/// - 42 characters (0x + 40 hex): Address variant
/// - 66 characters (0x + 64 hex): `PoolId` variant
///
/// # Errors
///
/// Returns an error if:
/// - String doesn't start with "0x"
/// - Length is neither 42 nor 66 characters
/// - Contains invalid hex characters
/// - Address checksum validation fails (for Address variant)
pub fn new_checked<T: AsRef<str>>(value: T) -> anyhow::Result<Self> {
let value = value.as_ref();
if !value.starts_with("0x") {
anyhow::bail!("Pool identifier must start with '0x', was: {value}");
}
match value.len() {
42 => {
validate_hex_string(value)?;
// Parse without strict checksum validation, then normalize to checksummed format
let addr = value
.parse::<Address>()
.map_err(|e| anyhow::anyhow!("Invalid address: {e}"))?;
// Store the checksummed version
Ok(Self::Address(Ustr::from(addr.to_checksum(None).as_str())))
}
66 => {
// PoolId variant (32 bytes)
validate_hex_string(value)?;
View on GitHub (pinned to 18893faf8b)
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.
Example fix
// before
let id = PoolIdentifier::new_checked(raw_addr)?;
// after
let normalized = if raw_addr.starts_with("0x") {
raw_addr.to_string()
} else {
format!("0x{raw_addr}")
};
let id = PoolIdentifier::new_checked(&normalized)?; Defensive patterns
Strategy: validation
Validate before calling
fn has_hex_prefix(s: &str) -> bool {
s.starts_with("0x") && s.len() > 2
}
// call PoolIdentifier::new_checked only after has_hex_prefix passes Try / catch
match PoolIdentifier::new_checked(value) {
Ok(id) => id,
Err(e) if e.to_string().contains("must start with '0x'") => {
let fixed = format!("0x{}", value.trim_start_matches("0x"));
PoolIdentifier::new_checked(&fixed)?
},
Err(e) => return Err(e),
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: "invalid id" errors: invalid identifier format — why libraries reject IDs before lookup, and how to fix them — this error's family across 37 libraries.
Related errors
- {label} must not be empty
- {label} contains invalid characters (only alphanumeric and u
- Invalid tick range: {tick_lower} >= {tick_upper}
- Ticks {tick_lower} and {tick_upper} must be multiples of the
- Invalid tick bounds for {tick_lower} and {tick_upper}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/004219c71f30b042.
Report an issue: GitHub.