tracel-ai/burn · error

Autobatcher should be able to send resulting probabilities.

Error message

Autobatcher should be able to send resulting probabilities.

What it means

Channel-invariant guard in `Autobatcher::flush_logits` (burn-rl): after computing batched logits from the queued inference states, the code sends each result back to its requester via an mpsc sender; the `.expect` fires only if the receiving end (the per-agent handle awaiting its probabilities) has been dropped — i.e., an agent was closed/removed while its request was still queued, so the batcher cannot deliver the result.

Source

Thrown at crates/burn-rl/src/policy/async_policy.rs:115

        }
        self.batch_action.clear();
    }

    pub fn flush_logits(&mut self) {
        if self.len_logits() == 0 {
            return;
        }
        let input: Vec<_> = self
            .batch_logits
            .iter()
            .map(|m| m.inference_state.clone())
            .collect();
        let output = self.inner_policy.forward(P::Observation::batch(input));
        let logits: Vec<_> = output.unbatch();
        for (i, item) in self.batch_logits.iter().enumerate() {
            item.sender
                .send(logits[i].clone())
                .expect("Autobatcher should be able to send resulting probabilities.");
        }
        self.batch_logits.clear();
    }

    pub fn update_policy(&mut self, policy_update: P::PolicyState) {
        if self.len_actions() > 0 {
            self.flush_actions();
        }
        if self.len_logits() > 0 {
            self.flush_logits();
        }
        self.inner_policy.update(policy_update);
    }

    pub fn policy_to_device(&mut self, device: &Device) {
        self.inner_policy = self.inner_policy.clone().to_device(device);
    }

View on GitHub (pinned to d16f7ba2ed)

Solutions

  1. Keep agent receivers alive until flush_logits completes for the pending batch
  2. Flush pending logits before decrementing agents or shutting down the policy
  3. Use cooperative cancellation so agents consume their pending logits first
  4. Handle send errors gracefully (skip dead receivers) instead of expecting
  5. sys

Example fix

// before
item.sender.send(logits[i].clone())
    .expect("Autobatcher should be able to send resulting probabilities.");
// after
if item.sender.send(logits[i].clone()).is_err() {
    // receiver dropped; skip this agent
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Before update_policy, confirm no pending logits belong to dead agents
let dead = self.batch_logits.iter().filter(|i| i.sender.is_closed()).count();
assert_eq!(dead, 0, "{dead} agents dropped before flush_logits");

Try / catch

if let Err(e) = item.sender.send(logits[i].clone()) {
    log::warn!("agent receiver dropped, skipping: {e}");
    continue;
}

Prevention

When it happens

Trigger: An agent dropped its receiver (task aborted, thread panicked, decrement_agents called) after push_logits queued the sender but before update_policy triggered flush_logits.

Common situations: Cancelling rollout workers mid-step; agent panics while the policy forward is in flight; shutdown ordering that tears down agents before flushing pending logits.

Related errors


AI-assisted analysis of tracel-ai/burn@d16f7ba2ed (2026-09-05). Data as JSON: /api/errors/a6db039cdcb5cb29. Report an issue: GitHub.