astrid-runtime/astrid · error
reply deserializes
Error message
reply deserializes
What it means
In the gateway sessions test request_capsule_accepts_live_registry_source_id, the reply from the sessions route is parsed with parse_list_response and unwrapped via expect("reply deserializes"). A panic here means the HTTP response body no longer matches the JSON shape parse_list_response expects (sessions list schema changed or the handler returned an error body).
Source
Thrown at crates/astrid-gateway/src/routes/sessions_tests.rs:441
});
let payload = build_list_payload(correlation_id, None, DEFAULT_LIMIT, false);
let value = request_capsule(
&bus,
TOPIC_LIST_REQUEST,
&response_topic,
payload,
correlation_id,
&principal,
None,
&[live_source],
CAPSULE_TIMEOUT,
)
.await
.expect("helper accepts the registry-provided source id");
capsule.await.expect("stand-in capsule task joins");
let parsed = parse_list_response(value).expect("reply deserializes");
assert!(parsed.sessions.is_empty());
}
#[test]
fn resolve_search_limit_defaults_and_caps() {
assert_eq!(resolve_search_limit(None).unwrap(), DEFAULT_SEARCH_LIMIT);
assert_eq!(resolve_search_limit(Some(0)).unwrap(), DEFAULT_SEARCH_LIMIT);
assert_eq!(resolve_search_limit(Some(50)).unwrap(), 50);
assert_eq!(
resolve_search_limit(Some(MAX_SEARCH_LIMIT)).unwrap(),
MAX_SEARCH_LIMIT
);
assert!(matches!(
resolve_search_limit(Some(MAX_SEARCH_LIMIT + 1)).unwrap_err(),
GatewayError::BadRequest(_)
));
}
View on GitHub (pinned to affd8760f4)
Solutions
- Diff the route's actual response JSON against what parse_list_response expects and update the parser or handler
- Run the test with the response body printed/logged to see the mismatched shape
- Restore the wire-format field names/types required by the frozen schema
- Check that the registry-provided source id path actually succeeded (an earlier failure can yield an error body)
Example fix
// before
let parsed = parse_list_response(value).expect("reply deserializes");
// after
let parsed = parse_list_response(&value)
.unwrap_or_else(|e| panic!("reply deserializes: {e}; body={value}")); Defensive patterns
Strategy: try-catch
Validate before calling
// assert the shape before parsing in test helpers
assert!(value.get("sessions").map_or(false, |s| s.is_array()),
"unexpected reply shape: {value}"); Type guard
fn is_list_reply(v: &serde_json::Value) -> bool {
v.get("sessions").map_or(false, serde_json::Value::is_array)
} Try / catch
let parsed = parse_list_response(&value)
.unwrap_or_else(|e| panic!("reply deserializes: {e}; body={value}")); Prevention
- Keep a frozen-schema test per route response type
- Print the response body in parser failure messages
- Treat any wire-format change as a deliberate schema-version bump
When it happens
Trigger: Running the test after changing the sessions list response serialization (renamed/removed fields, changed envelope), or when the route under test returns an error/empty body instead of the expected list JSON.
Common situations: Schema drift between the handler and the test's frozen parser; a regression in the route returning a JSON error object; serde field-type changes making deserialization fail.
Understand the failure class
Background: "failed to unmarshal" / json.Unmarshal errors: why parsing a response into a Go struct fails and how to fix it — this error's family across 23 libraries.
Related errors
- present session
- frozen search shape deserializes
- tool_describe payload is not valid JSON or has an unexpected
- frozen SUMMARY deserializes
- sparse SUMMARY deserializes
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/75425ff5aba400a0.
Report an issue: GitHub.