{"record":{"id":"c0ea6eb1172b1d79","repo":"FuelLabs/fuel-core","slug":"error-c0ea6e","errorCode":null,"errorMessage":"{}","messagePattern":"\\{\\}","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/services/p2p/src/service.rs","lineNumber":1360,"sourceCode":"    }\n\n    pub fn broadcast_preconfirmations(\n        &self,\n        preconfirmations: Arc<P2PPreConfirmationMessage>,\n    ) -> anyhow::Result<()> {\n        self.request_sender\n            .try_send(TaskRequest::BroadcastPreConfirmations(preconfirmations))?;\n        Ok(())\n    }\n\n    pub async fn get_all_peers(&self) -> anyhow::Result<Vec<(PeerId, PeerInfo)>> {\n        let (sender, receiver) = oneshot::channel();\n\n        self.request_sender\n            .send(TaskRequest::GetAllPeerInfo { channel: sender })\n            .await?;\n\n        receiver.await.map_err(|e| anyhow!(\"{}\", e))\n    }\n\n    pub async fn reserved_peer_network_height(\n        &self,\n    ) -> anyhow::Result<Option<BlockHeight>> {\n        let (sender, receiver) = oneshot::channel();\n\n        self.request_sender\n            .send(TaskRequest::GetReservedPeerNetworkHeight { channel: sender })\n            .await?;\n\n        receiver.await.map_err(|e| anyhow!(\"{}\", e))\n    }\n\n    pub fn subscribe_new_peers(&self) -> broadcast::Receiver<FuelPeerId> {\n        self.new_tx_subscription_broadcast.subscribe()\n    }\n","sourceCodeStart":1342,"sourceCodeEnd":1378,"githubUrl":"https://github.com/FuelLabs/fuel-core/blob/add100d30d21498e8528c46be8567fbd2ea019af/crates/services/p2p/src/service.rs#L1342-L1378","documentation":"`get_all_peer_info` sends a `TaskRequest::GetAllPeerInfo` over an mpsc channel to the P2P service's background task and awaits the reply on a oneshot channel. The `\"{}\"` anyhow error wraps a `oneshot::error::RecvError`, which occurs only when the sender half was dropped before replying — i.e. the P2P task (or the code holding the reply sender) is gone. It therefore means the P2P service's internal task is no longer running to answer the query, not that peer data was unavailable.","triggerScenarios":"Calling `P2PService::get_all_peer_info()` (service.rs:1360) after the P2P background task has stopped or is shutting down: the task loop exited, the `request_sender` channel send still succeeded (or the receiver was dropped concurrently), and the oneshot reply sender was dropped without sending.","commonSituations":"Node shutdown racing with an in-flight peer-info query; the P2P service task panicked or was aborted while the outer service handle is still alive; tests or code holding a stale `Service`/`Shared` handle after `stop()` was called.","solutions":["Check that the fuel-core P2P service is still running and has not been stopped before calling `get_all_peer_info`.","Inspect P2P task logs for a panic or early exit in the request-processing loop and fix the underlying task crash.","Treat the `RecvError` as a service-lifecycle signal: re-create/restart the P2P service instead of retrying the query against a dead task.","If this occurs during shutdown races, guard call sites to not query the service once shutdown has begun."],"exampleFix":"// before\nlet peers = p2p_service.get_all_peer_info().await?;\n// after\nif p2p_service.is_started() {\n    let peers = p2p_service.get_all_peer_info().await\n        .map_err(|e| e.context(\"P2P task dropped the peer-info reply; service likely stopped\"))?;\n} else {\n    return Err(anyhow!(\"P2P service is not running\"));\n}","handlingStrategy":"try-catch","validationCode":"// check service health before querying\nif !p2p_service.is_started() {\n    return Err(anyhow!(\"P2P service not started; skipping get_all_peer_info\"));\n}","typeGuard":"fn peers_reply_ok(res: &anyhow::Result<Vec<PeerInfo>>) -> bool {\n    res.as_ref().map(|p| !p.is_empty()).unwrap_or(false)\n}","tryCatchPattern":"match p2p_service.get_all_peer_info().await {\n    Ok(peers) => peers,\n    Err(e) if e.to_string().contains(\"channel closed\") || e.to_string().contains(\"RecvError\") => {\n        tracing::warn!(\"P2P task unavailable: {e:#}\");\n        Vec::new() // or restart the service\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Only call peer-info APIs while the P2P service task is confirmed running.","Watch for node shutdown signals and stop querying services once shutdown begins.","Log and alert on repeated channel-closed errors — they indicate the P2P task died.","Keep a supervisor that restarts the P2P service after unexpected task termination."],"tags":["p2p","oneshot-channel","service-lifecycle","async"],"backgroundTag":"channel-closed","analyzedSha":"add100d30d21498e8528c46be8567fbd2ea019af","analyzedAt":"2026-09-05T18:46:12.018Z","contentChangedAt":"2026-09-05T18:46:12.018Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}