{"record":{"id":"10d8db3e9e0409be","repo":"tracel-ai/burn","slug":"should-be-able-to-send-message-to-inference-server-10d8db","errorCode":null,"errorMessage":"should be able to send message to inference_server.","messagePattern":"should be able to send message to inference_server\\.","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/burn-rl/src/policy/async_policy.rs","lineNumber":290,"sourceCode":"        action_receiver\n            .recv()\n            .expect(\"AsyncPolicy should receive queued probabilities.\")\n    }\n\n    fn action(\n        &mut self,\n        states: Self::Observation,\n        deterministic: bool,\n    ) -> (Self::Action, Vec<Self::ActionContext>) {\n        let (action_sender, action_receiver) = std::sync::mpsc::channel();\n        let item = ActionItem {\n            sender: action_sender,\n            inference_state: states,\n            deterministic,\n        };\n        self.inference_state_sender\n            .send(InferenceMessage::ActionMessage(item))\n            .expect(\"should be able to send message to inference_server.\");\n        let action = action_receiver\n            .recv()\n            .expect(\"AsyncPolicy should receive queued actions.\");\n        (action.action, action.context)\n    }\n\n    fn update(&mut self, update: Self::PolicyState) {\n        self.inference_state_sender\n            .send(InferenceMessage::PolicyUpdate(update))\n            .expect(\"AsyncPolicy should be able to send policy state.\")\n    }\n\n    fn state(&self) -> Self::PolicyState {\n        let (sender, receiver) = mpsc::channel();\n        self.inference_state_sender\n            .send(InferenceMessage::PolicyRequest(sender))\n            .expect(\"should be able to send message to inference_server.\");\n        receiver","sourceCodeStart":272,"sourceCodeEnd":308,"githubUrl":"https://github.com/tracel-ai/burn/blob/d16f7ba2ed0d41408189384044cc886fb4c8f957/crates/burn-rl/src/policy/async_policy.rs#L272-L308","documentation":"AsyncPolicy::action sends an ActionMessage (observation, determinism flag and reply Sender) to the autobatcher thread and panics if the send fails. Failure means the inference thread's receiver is gone: the thread panicked on an earlier message or exited its recv loop, so this AsyncPolicy handle is dead and the caller cannot obtain an action.","triggerScenarios":"Calling action() after the autobatcher thread terminated: a previous reply-send panic in flush_actions/flush_logits (e.g. an agent stopped waiting for its action), a panic inside inner_policy.action during batched inference, or all clones of the AsyncPolicy having been dropped elsewhere letting the thread exit with RecvError.","commonSituations":"Multi-agent RL environments sharing one AsyncPolicy where a single agent's misbehaviour (dropped receiver, timeout) crashes the inference server and every remaining agent panics on its next action() call; CUDA OOM in the inner policy ending the thread mid-rollout.","solutions":["Locate and fix the initial autobatcher-thread failure in the logs; this panic is secondary fallout.","Rebuild the AsyncPolicy with AsyncPolicy::new once the server thread is dead.","Prevent inner-policy panics (validate batched observation shapes, handle device errors) to keep the shared thread alive.","Replace reply-send expects in the server with logged errors so one dead client cannot take down the server for all clients."],"exampleFix":"// before\nself.inference_state_sender\n    .send(InferenceMessage::ActionMessage(item))\n    .expect(\"should be able to send message to inference_server.\");\n// after\nif self.inference_state_sender.send(InferenceMessage::ActionMessage(item)).is_err() {\n    log::error!(\"Inference server thread is down; cannot request action\");\n    return fallback_action(states); // or surface an error to the caller\n}","handlingStrategy":"try-catch","validationCode":"// Pre-validate the observation before sending it to the shared batcher\ndebug_assert_eq!(states.vec.len(), expected_obs_size, \"observation size mismatch would break batched inference\");","typeGuard":null,"tryCatchPattern":"let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| policy.action(states, deterministic)));\nmatch result {\n    Ok((action, ctx)) => (action, ctx),\n    Err(_) => { rebuild_async_policy(); fallback_action(states) }\n}","preventionTips":["Fix the first autobatcher-thread panic; every send failure means the thread is already dead.","Validate per-agent observation shapes before batching to prevent inner_policy.action panics.","Replace reply-send expects in flush_actions with logged errors so a single dead client cannot crash the server.","Rebuild the AsyncPolicy after any detected thread death instead of reusing stale clones."],"tags":["rust","mpsc-channel","panics","multi-agent"],"backgroundTag":"mpsc-receiver-dropped","analyzedSha":"d16f7ba2ed0d41408189384044cc886fb4c8f957","analyzedAt":"2026-09-05T13:19:14.260Z","contentChangedAt":"2026-09-05T13:19:14.260Z","schemaVersion":2},"datasetVersion":"2026-09-12T17:17:11.597Z"}