{"record":{"id":"e42563147ca968a7","repo":"nautechsystems/nautilus_trader","slug":"market-shard-receiver-unavailable-after-connect","errorCode":null,"errorMessage":"Market shard receiver unavailable after connect","messagePattern":"Market shard receiver unavailable after connect","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/adapters/polymarket/src/websocket/pool.rs","lineNumber":659,"sourceCode":"    async fn connect_new_shard(&self, is_primary: bool) -> anyhow::Result<usize> {\n        if self.closed.load(Ordering::Acquire) {\n            anyhow::bail!(\"Market connection pool is closed\");\n        }\n\n        let id = if is_primary {\n            PRIMARY_SHARD_ID\n        } else {\n            let state = self.state.lock();\n            available_shard_id(&state)\n        };\n\n        let mut client = self.market_client(self.subscribe_new_markets, id);\n        client.connect().await?;\n\n        let handle = client.clone_subscription_handle();\n        let rx = client\n            .take_message_receiver()\n            .ok_or_else(|| anyhow::anyhow!(\"Market shard receiver unavailable after connect\"))?;\n        let forwarder = match self.spawn_forwarder(rx, is_primary) {\n            Ok(forwarder) => forwarder,\n            Err((e, forwarder)) => {\n                let shard = Box::new(ShardEntry {\n                    client,\n                    handle,\n                    forwarder,\n                    owned: 0,\n                    closing: true,\n                });\n\n                if let Err(close_error) = self.close_shard(id, shard).await {\n                    anyhow::bail!(\n                        \"Failed to start market shard forwarder: {e}; startup rollback failed: \\\n                         {close_error}\"\n                    );\n                }\n                anyhow::bail!(\"Failed to start market shard forwarder: {e}\");","sourceCodeStart":641,"sourceCodeEnd":677,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/polymarket/src/websocket/pool.rs#L641-L677","documentation":"When the WebSocket shard pool grows (connect_new_shard), it creates a new market client, connects, and then must take ownership of the client's message receiver. If take_message_receiver returns None after a successful connect, the pool's internal invariant is broken — the receiver was already taken or was never set — so the shard cannot be brought up and this error aborts connect_new_shard (invoked from assign).","triggerScenarios":"Calling connect_new_shard when the freshly constructed client's receiver channel was already consumed, or the client implementation changed so no receiver is created during connect().","commonSituations":"Concurrent pool resizing racing on the same client; a version mismatch/bug in the market client that skips receiver setup; reusing a client instance for a second shard.","solutions":["Check that each ShardEntry/market client is used exactly once — never reuse a connected client for another shard","Guard pool resizing against concurrent assign calls (serialize shard creation)","Upgrade the polymarket adapter — this indicates an internal invariant break that may be a fixed bug","Capture the client state at failure and file an issue with logs if reproducible"],"exampleFix":"// before: panics the whole assign flow on None\nlet rx = client.take_message_receiver()\n    .ok_or_else(|| anyhow::anyhow!(\"Market shard receiver unavailable after connect\"))?;\n// after: retry shard creation once\nlet rx = client.take_message_receiver()\n    .or_else(|| { client.connect(); client.take_message_receiver() })\n    .ok_or_else(|| anyhow::anyhow!(\"Market shard receiver unavailable after connect\"))?;","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"match connect_new_shard(id).await {\n    Ok(shard) => /* register shard */,\n    Err(e) if e.to_string().contains(\"receiver unavailable\") => {\n        log::error!(\"pool invariant broken: {e}; rebuilding pool\");\n        // rebuild or restart the pool\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Never reuse a connected market client across shards","Serialize pool-resize operations to avoid racing on receivers","Keep the adapter at a version where pool connect/take_receiver pairing is intact"],"tags":["polymarket","websocket","internal-state","sharding"],"backgroundTag":"internal-invariant-violation","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}