astrid-runtime/astrid · error
helper returns the scoped reply
Error message
helper returns the scoped reply
What it means
This panic comes from `.expect("helper returns the scoped reply")` on the awaited result of the request-capsule helper in `request_capsule_round_trips_update_reply`. The helper waited `CAPSULE_TIMEOUT` for a reply on `TOPIC_UPDATE_RESPONSE_PREFIX.<correlation_id>` and returned Err — typically a timeout because no acceptable reply arrived on the scoped topic.
Source
Thrown at crates/astrid-gateway/src/routes/sessions_tests.rs:780
message: msg,
});
});
let body = serde_json::json!({ "title": "renamed" });
let payload = build_update_payload(correlation_id, "sess-1", &body).unwrap();
let value = request_capsule(
&bus,
TOPIC_UPDATE_REQUEST,
&response_topic,
payload,
correlation_id,
&principal,
None,
&[test_provider_source_id()],
CAPSULE_TIMEOUT,
)
.await
.expect("helper returns the scoped reply");
capsule.await.expect("stand-in capsule joins");
let summary = parse_session_field(&value)
.unwrap()
.expect("present session");
assert_eq!(summary.session_id, "sess-1");
assert_eq!(summary.title.as_deref(), Some("renamed"));
}
/// A reply stamped for a different principal is ignored. This protects a
/// same-topic reply from satisfying another caller's request.
#[tokio::test]
async fn request_capsule_ignores_wrong_principal_reply() {
let bus = Arc::new(EventBus::new());
let principal = PrincipalId::new("alice").expect("valid principal");
let correlation_id = "corr-want-principal";
let response_topic = format!("{TOPIC_LIST_RESPONSE_PREFIX}.{correlation_id}");
View on GitHub (pinned to affd8760f4)
Solutions
- Verify the stand-in capsule publishes to `response_topic` (TOPIC_UPDATE_RESPONSE_PREFIX + correlation id) with a matching principal and the capsule's kernel source id.
- Increase CAPSULE_TIMEOUT or make it configurable for slow CI runners.
- Log the helper's error variant to distinguish timeout from filter-rejection.
- Ensure the request the capsule matched carried the same correlation_id the helper is listening for.
Example fix
// before
let value = update_session(...).await.expect("helper returns the scoped reply");
// after
let value = update_session(...).await
.unwrap_or_else(|e| panic!("helper returns the scoped reply: {e:?}")); Defensive patterns
Strategy: retry
Try / catch
let value = helper(...).await
.unwrap_or_else(|e| panic!("helper returns the scoped reply: {e:?}")); Prevention
- Publish replies on the correlation-scoped topic with matching principal and source id
- Use a generous CAPSULE_TIMEOUT in CI
- Log the helper error variant to distinguish timeout from rejection
When it happens
Trigger: The stand-in capsule never publishes the updated SUMMARY reply on the scoped response topic, publishes it with the wrong principal/source stamp so the helper filters it out, or the helper times out at CAPSULE_TIMEOUT before the reply lands.
Common situations: Reply published to the unscoped topic instead of the correlation-scoped one; response stamped with a different principal or source_id and rejected by the defensive checks; CAPSULE_TIMEOUT too short under CI load; topic prefix constants out of sync.
Understand the failure class
Background: Request timed out: what client-side request timeouts mean across libraries (Request timed out, TIMED_OUT, APITimeoutError) — this error's family across 39 libraries.
Related errors
- our own event is delivered
- request arrives
- stand-in capsule joins
- timeout exceeds upper bound ({TIMEOUT_SECS_UPPER_BOUND}s)
- bus admin request timed out after {:?} waiting for {want_res
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/82dfa91bedf24e5b.
Report an issue: GitHub.