tracel-ai/burn · error
AsyncPolicy should receive queued actions.
Error message
AsyncPolicy should receive queued actions.
What it means
After queueing an ActionMessage, AsyncPolicy::action blocks on action_receiver.recv() and panics on Err, which occurs when the reply Sender was dropped without sending a value. The autobatcher sends exactly one reply per item in flush_actions, so Err means that flush never happened: the server thread died (panic or loop exit) before this item was batched and processed.
Source
Thrown at crates/burn-rl/src/policy/async_policy.rs:293
}
fn action(
&mut self,
states: Self::Observation,
deterministic: bool,
) -> (Self::Action, Vec<Self::ActionContext>) {
let (action_sender, action_receiver) = std::sync::mpsc::channel();
let item = ActionItem {
sender: action_sender,
inference_state: states,
deterministic,
};
self.inference_state_sender
.send(InferenceMessage::ActionMessage(item))
.expect("should be able to send message to inference_server.");
let action = action_receiver
.recv()
.expect("AsyncPolicy should receive queued actions.");
(action.action, action.context)
}
fn update(&mut self, update: Self::PolicyState) {
self.inference_state_sender
.send(InferenceMessage::PolicyUpdate(update))
.expect("AsyncPolicy should be able to send policy state.")
}
fn state(&self) -> Self::PolicyState {
let (sender, receiver) = mpsc::channel();
self.inference_state_sender
.send(InferenceMessage::PolicyRequest(sender))
.expect("should be able to send message to inference_server.");
receiver
.recv()
.expect("AsyncPolicy should be able to receive policy state.")
}View on GitHub (pinned to d16f7ba2ed)
Solutions
- Diagnose the root cause of the server-thread death from logs; this panic is a symptom, not the cause.
- Keep increment_agents/decrement_agents counts in sync with live agents so batches always flush and requests never hang until shutdown.
- Make the server flush or reject pending items gracefully on shutdown so waiting callers get a real error instead of a dropped channel.
- Use recv_timeout with a descriptive panic/error on the caller side to distinguish 'server dead' from 'slow inference'.
Example fix
// before
let action = action_receiver
.recv()
.expect("AsyncPolicy should receive queued actions.");
// after
let action = action_receiver
.recv_timeout(std::time::Duration::from_secs(60))
.unwrap_or_else(|err| panic!("No action returned by inference server (thread dead or batch stalled): {}", err)); Defensive patterns
Strategy: retry
Validate before calling
// Ensure agent accounting is consistent before requesting actions assert!(registered_agents.load(Ordering::Relaxed) > 0, "agents not registered; action batch may never flush");
Try / catch
match action_receiver.recv_timeout(Duration::from_secs(60)) {
Ok(ac) => (ac.action, ac.context),
Err(RecvTimeoutError::Timeout) => return Err(anyhow::anyhow!("action request stalled; batch never flushed")),
Err(RecvTimeoutError::Disconnected) => return Err(anyhow::anyhow!("inference server died before returning an action")),
} Prevention
- Use recv_timeout with a descriptive error instead of a bare expect on recv.
- Keep increment/decrement agent counts matched to live callers so batches always flush.
- Investigate flush_actions/inner_policy panics in logs — they drop all queued reply senders at once.
- Ensure orderly shutdown flushes pending ActionItems or replies with errors.
When it happens
Trigger: An earlier panic in the autobatcher thread (failed reply send to another agent, or inner_policy.action panicking on the batched input such as a device/shape error) dropping all queued senders; or the thread exiting its loop so queued ActionItems are never flushed and their senders are dropped at teardown.
Common situations: One agent aborting its request (dropping its receiver) panics flush_actions' reply send, killing the thread and turning every other waiting agent's recv into this panic; num_agents accounting bugs causing batches that never reach the flush threshold, later compounded by a thread shutdown.
Related errors
- should be able to send message to inference_server.
- Autobatcher should be able to send current policy state.
- Can send message to autobatcher.
- Should be able to send message to inference_server
- AsyncPolicy should receive queued probabilities.
AI-assisted analysis of tracel-ai/burn@d16f7ba2ed (2026-09-05).
Data as JSON: /api/errors/ff2a5cc6c2b905ce.
Report an issue: GitHub.