nautechsystems/nautilus_trader · error
wss_rpc_url is required
Error message
wss_rpc_url is required
What it means
BlockchainDataClientCore::new reads `config.wss_rpc_url` when live WebSocket data is enabled (not using HyperSync) and unwraps it with `expect("wss_rpc_url is required")`. The guard `config.wss_rpc_url.is_some()` makes the panic nearly unreachable, but it documents that a WebSocket URL is mandatory on this path — a None here is a config/invariant violation.
Source
Thrown at crates/adapters/blockchain/src/data/core.rs:187
#[must_use]
pub fn new(
config: BlockchainDataClientConfig,
hypersync_tx: Option<tokio::sync::mpsc::UnboundedSender<BlockchainMessage>>,
data_tx: Option<tokio::sync::mpsc::UnboundedSender<DataEvent>>,
cancellation_token: tokio_util::sync::CancellationToken,
) -> Self {
let chain = config.chain.clone();
let cache = BlockchainCache::new(chain.clone());
// Log RPC endpoints being used
log::debug!(
"Initializing blockchain data client for '{}' with HTTP RPC: {}",
chain.name,
REDACTED
);
let rpc_client = if !config.use_hypersync_for_live_data && config.wss_rpc_url.is_some() {
let wss_rpc_url = config.wss_rpc_url.clone().expect("wss_rpc_url is required");
log::debug!("WebSocket RPC URL: {REDACTED}");
Some(Self::initialize_rpc_client(
chain.name,
wss_rpc_url.into_inner(),
config.transport_backend,
config.proxy_url.clone().map(|value| value.into_inner()),
))
} else {
log::debug!("Using HyperSync for live data (no WebSocket RPC)");
None
};
let http_rpc_client = Arc::new(BlockchainHttpRpcClient::new(
config.http_rpc_url.clone().into_inner(),
config.rpc_requests_per_second,
config.proxy_url.clone().map(|value| value.into_inner()),
));
let multicall_calls_per_rpc_request = config.multicall_calls_per_rpc_request;
let erc20_contract = Erc20Contract::new(View on GitHub (pinned to 18893faf8b)
Solutions
- Set `wss_rpc_url` (e.g. `wss://mainnet.infura.io/ws/v3/<key>`) in the client config when HyperSync live data is disabled.
- Alternatively enable `use_hypersync_for_live_data = true` so the WSS URL is not required.
- Check the config key spelling/section so the URL actually deserializes into `wss_rpc_url`.
- Validate the config (wss URL present iff not using HyperSync) before calling `new`.
Example fix
// before
let config = BlockchainDataClientConfig {
use_hypersync_for_live_data: false,
wss_rpc_url: None, // panics in new()
..Default::default()
};
// after
let config = BlockchainDataClientConfig {
use_hypersync_for_live_data: false,
wss_rpc_url: Some(SecretString::from("wss://mainnet.infura.io/ws/v3/<key>".to_string())),
..Default::default()
}; Defensive patterns
Strategy: validation
Validate before calling
if !config.use_hypersync_for_live_data && config.wss_rpc_url.is_none() {
return Err(anyhow!("wss_rpc_url is required when use_hypersync_for_live_data is false"));
} Type guard
fn wss_ready(config: &BlockchainDataClientConfig) -> bool {
config.use_hypersync_for_live_data || config.wss_rpc_url.is_some()
} Try / catch
// Rust: check the option yourself before constructing
let wss = match (&config.use_hypersync_for_live_data, &config.wss_rpc_url) {
(false, Some(url)) => Some(url.clone()),
(false, None) => return Err(anyhow!("wss_rpc_url is required")),
(true, _) => None,
}; Prevention
- Always set wss_rpc_url when live WebSocket data is enabled (HyperSync disabled).
- Set use_hypersync_for_live_data = true if you do not have a WSS endpoint.
- Validate the client config (required fields per mode) before calling `new`.
- Check config key spelling and sections so values actually deserialize.
When it happens
Trigger: Constructing the client with `use_hypersync_for_live_data = false` and `wss_rpc_url = None` (or a config that deserializes it as None while another thread mutates it), reaching the `.expect` on the cloned Option.
Common situations: Config file or env omitting the WSS RPC URL while live-data mode requires it; typo'd config key so the field defaults to None; config builder leaving the optional field unset.
Understand the failure class
Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.
Related errors
- slots lock poisoned
- InstrumentState channel requires kind and currency parameter
- Invalid factory address for DEX {name} on chain {chain} for
- Lighter execution client requires credentials; set private_k
- Either replay `options` or `stream_options` must be provided
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/dc92ac416227c760.
Report an issue: GitHub.