{"record":{"id":"e72c265b422847fa","repo":"nautechsystems/nautilus_trader","slug":"description-endpoint-host-is-required","errorCode":null,"errorMessage":"{description} endpoint host is required","messagePattern":"(.+?) endpoint host is required","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/blockchain/src/rpc/http.rs","lineNumber":922,"sourceCode":"            .ok_or_else(|| BroadcastError::Failed(\"Broadcast returned no result\".to_string()))?;\n\n        B256::from_str(&hex_string)\n            .map_err(|e| BroadcastError::Failed(format!(\"Failed to parse broadcast result: {e}\")))\n    }\n}\n\n#[cfg(feature = \"hypersync\")]\npub(crate) fn validate_execution_endpoint(\n    endpoint: &str,\n    description: &str,\n) -> anyhow::Result<Url> {\n    let url =\n        Url::parse(endpoint).map_err(|_| anyhow::anyhow!(\"Invalid {description} endpoint\"))?;\n    anyhow::ensure!(\n        matches!(url.scheme(), \"http\" | \"https\"),\n        \"{description} endpoint must use HTTPS or canonical loopback HTTP\"\n    );\n    anyhow::ensure!(\n        url.host().is_some(),\n        \"{description} endpoint host is required\"\n    );\n    anyhow::ensure!(\n        url.fragment().is_none(),\n        \"{description} endpoint fragments are unsupported\"\n    );\n    anyhow::ensure!(\n        url.scheme() == \"https\" || is_canonical_loopback_endpoint(endpoint),\n        \"{description} endpoint must use HTTPS unless its host is a canonical loopback IP literal\"\n    );\n    Ok(url)\n}\n\nfn is_canonical_loopback_endpoint(endpoint: &str) -> bool {\n    let Some((scheme, rest)) = endpoint.split_once(\"://\") else {\n        return false;\n    };","sourceCodeStart":904,"sourceCodeEnd":940,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/blockchain/src/rpc/http.rs#L904-L940","documentation":"Thrown by `validate_execution_endpoint` when the parsed URL has no host component. An HTTP JSON-RPC endpoint must address a host, so scheme-only or opaque URLs (e.g. `http:` with nothing after it, or `mailto:`-like forms) fail this check.","triggerScenarios":"Passing a URL that parses but yields `url.host() == None` — e.g. `\"http://\"`, `\"https:///path\"`, or a scheme-only string — to `new`, `normalize_endpoint`, or validation tests.","commonSituations":"Config value partially deleted leaving `http://` behind; templating variable left empty so the URL becomes `https://${HOST}` with HOST unset; string concatenation bugs building the endpoint.","solutions":["Ensure the configured value includes a host: `https://your-node.example.com:8545`.","Check that environment variable/templating substitution actually populated the host part.","Validate the endpoint string at startup (fail fast) rather than at first RPC call."],"exampleFix":"// before\nlet endpoint = &format!(\"https://{}\", std::env::var(\"RPC_HOST\").unwrap_or_default()); // empty host\n// after\nlet endpoint = &format!(\"https://{}\", std::env::var(\"RPC_HOST\").expect(\"RPC_HOST must be set\"));","handlingStrategy":"validation","validationCode":"let url = url::Url::parse(endpoint)?;\nanyhow::ensure!(url.host().is_some(), \"endpoint is missing a host: '{endpoint}'\");","typeGuard":"fn has_host(s: &str) -> bool {\n    url::Url::parse(s).map(|u| u.host().is_some()).unwrap_or(false)\n}","tryCatchPattern":"let endpoint = format!(\"https://{}\", host_var); // ensure substitution happened\nlet client = HttpRpcClient::new(&endpoint).map_err(|e| {\n    if e.to_string().contains(\"host is required\") {\n        anyhow::anyhow!(\"RPC_HOST is unset or empty; got endpoint '{endpoint}'\")\n    } else { e.into() }\n})?;","preventionTips":["Use expect/unwrap_or_die on env vars that build endpoint URLs so empty values fail loudly.","Prefer whole-URL config values over string concatenation of host+path.","Add a startup assertion that every endpoint URL has a host."],"tags":["url","config","validation"],"backgroundTag":"invalid-url-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"}