nautechsystems/nautilus_trader · error

cannot override URL: Arc has multiple references

Error message

cannot override URL: Arc has multiple references

What it means

The Hyperliquid client stores shared configuration in an `Arc`; `set_base_info_url` uses `Arc::get_mut` to override the URL in place, which only succeeds when the Arc has exactly one reference (strong count 1). The method is intended for test setup before the client is shared. If the inner Arc has been cloned or shared (e.g. across tasks), mutating is impossible and the method panics.

Source

Thrown at crates/adapters/hyperliquid/src/http/client.rs:1055

            .filter(|cached_cloid| **cached_cloid == cloid)
            .count();

        (mapping_count == 1).then_some(cloid)
    }

    /// Removes the cached CLOID for a client order ID.
    pub fn remove_client_order_id_cloid(&self, client_order_id: &ClientOrderId) -> Option<Cloid> {
        self.client_order_id_cloids.lock().remove(client_order_id)
    }

    /// Overrides the base info URL (for testing with mock servers).
    ///
    /// # Panics
    ///
    /// Panics if the inner `Arc` has multiple references.
    pub fn set_base_info_url(&mut self, url: String) {
        Arc::get_mut(&mut self.inner)
            .expect("cannot override URL: Arc has multiple references")
            .set_base_info_url(url);
    }

    /// Overrides the base exchange URL (for testing with mock servers).
    ///
    /// # Panics
    ///
    /// Panics if the inner `Arc` has multiple references.
    pub fn set_base_exchange_url(&mut self, url: String) {
        Arc::get_mut(&mut self.inner)
            .expect("cannot override URL: Arc has multiple references")
            .set_base_exchange_url(url);
    }

    /// Creates an authenticated client from environment variables for the specified network.
    ///
    /// # Errors
    ///

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Call `set_base_info_url` immediately after construction, before any clone or sharing of the client.
  2. For runtime reconfiguration, use the constructor with an explicit URL (`HyperliquidHttpClient::new`) and rebuild/re-share the client instead of mutating.
  3. Wrap the override in a check or use interior mutability (RwLock) in the inner state if runtime mutation is genuinely required.
  4. In tests, build the client with the mock-server URL from the start rather than overriding afterwards.

Example fix

// before
let client = HyperliquidHttpClient::default();
let shared = client.clone();
client.set_base_info_url(mock_url); // panics: Arc has multiple refs
// after
let mut client = HyperliquidHttpClient::default();
client.set_base_info_url(mock_url); // before any clone/sharing
let shared = client.clone();
Defensive patterns

Strategy: validation

Validate before calling

if Arc::strong_count(&client.inner) != 1 {
    // URL already shared; rebuild the client with new() instead of overriding
}

Prevention

When it happens

Trigger: Calling `set_base_info_url` after the client's inner Arc was cloned — e.g. after passing the client (or a clone) to spawned tasks, other components, or holding multiple handles; also calling it concurrently with any other holder of the inner state.

Common situations: Test code that shares the client with a websocket client or cache before trying to point it at a mock server; production code calling the setter on a long-lived, already-shared client; reconfiguration attempts at runtime instead of construction time.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08). Data as JSON: /api/errors/aa28723eab666b20. Report an issue: GitHub.