astrid-runtime/astrid · error
request arrives
Error message
request arrives
What it means
This panic comes from `req_rx.recv().await.expect("request arrives")` inside the stand-in capsule task in `request_capsule_round_trips_update_reply`. It fires when the subscribed EventBus topic stream ends (recv returns None) before any `update` request event is delivered, i.e. the subscription closed without a message.
Source
Thrown at crates/astrid-gateway/src/routes/sessions_tests.rs:729
));
}
/// Live round-trip over a real `EventBus` for the `update` verb: the
/// stand-in capsule receives the principal-stamped, present-keys-only
/// patch and replies with an updated SUMMARY on the scoped topic.
#[tokio::test]
async fn request_capsule_round_trips_update_reply() {
let bus = Arc::new(EventBus::new());
let principal = PrincipalId::new("alice").expect("valid principal");
let correlation_id = "corr-upd-1";
let response_topic = format!("{TOPIC_UPDATE_RESPONSE_PREFIX}.{correlation_id}");
let mut req_rx = bus.subscribe_topic(TOPIC_UPDATE_REQUEST.to_string());
let bus_capsule = Arc::clone(&bus);
let resp_topic = response_topic.clone();
let cid = correlation_id.to_string();
let capsule = tokio::spawn(async move {
let event = req_rx.recv().await.expect("request arrives");
let AstridEvent::Ipc { message, .. } = &*event else {
panic!("expected IPC request");
};
// Principal-stamped, and the patch carries only the sent key.
assert_eq!(message.principal.as_deref(), Some("alice"));
assert_ne!(message.source_id, Uuid::nil());
assert_eq!(message.origin, MessageOrigin::RemoteGateway);
if let IpcPayload::RawJson(v) = &message.payload {
assert_eq!(v["title"], "renamed");
assert!(v.get("archived").is_none(), "absent key not forwarded");
} else {
panic!("expected RawJson payload");
}
let reply = serde_json::json!({
"correlation_id": cid,
"session": {
"session_id": "sess-1",
"title": "renamed",View on GitHub (pinned to affd8760f4)
Solutions
- Confirm the helper publishes to exactly `TOPIC_UPDATE_REQUEST` for the update verb.
- Check whether the update helper returned Err and surface that error first; a helper failure usually starves this receiver.
- Keep the publisher (bus Arc) alive for the duration of the test so the channel cannot close early.
- Replace expect with explicit matching on None vs Some to distinguish channel-closed from timeout.
Example fix
// before
let event = req_rx.recv().await.expect("request arrives");
// after
let Some(event) = req_rx.recv().await else {
panic!("update request channel closed before a request arrived");
}; Defensive patterns
Strategy: try-catch
Try / catch
match req_rx.recv().await {
Some(event) => { /* handle */ }
None => panic!("request channel closed before delivery"),
} Prevention
- Keep the publisher Arc alive for the whole test
- Assert topic constants are shared between producer and consumer
- Surface helper errors before awaiting the receiving task
When it happens
Trigger: The helper under test (`update_session` path) never publishes an `AstridEvent::Ipc` on `TOPIC_UPDATE_REQUEST` before the capsule task's receiver channel closes — e.g. the helper errored out early, published on a different topic name, or the EventBus dropped its publisher side.
Common situations: Topic constant renamed so producer and consumer disagree; the helper returns Err before publishing (surface it via the other expect at line ~780); async task raced and the bus was dropped; EventBus subscription API changed semantics so recv now ends on idle.
Related errors
- helper returns the scoped reply
- stand-in capsule joins
- our own event is delivered
- empty page deserializes
- alice
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/2ca44301575808b1.
Report an issue: GitHub.