EpicGames/lore · error
response parse should work
Error message
response parse should work
What it means
A panic from `.expect("response parse should work")` on `QueryResponse::parse(collapse_bytes(&handle_output))` in `immutable_local_query_routes_to_local_store`. The handler completed but the returned bytes are not a valid QueryResponse — likely an empty body, an error-encoded response, or a serialization change in QueryResponse. The library throws this when the response bytes do not conform to the expected QueryResponse wire format.
Solutions
- Print `collapse_bytes(&handle_output)` (length + hex) before parsing to see what the handler actually produced.
- Check that the handler returned a QueryResponse and not an empty/error body (an early `return Ok(vec![])` path yields unparseable bytes).
- Verify QueryResponse::parse and its serialization counterpart are in sync after any format change.
- Ensure `collapse_bytes` concatenates all chunks including the header the parser expects.
Example fix
// before
let response = QueryResponse::parse(collapse_bytes(&handle_output))
.expect("response parse should work");
// after
let raw = collapse_bytes(&handle_output);
let response = QueryResponse::parse(raw.clone())
.unwrap_or_else(|e| panic!("response parse failed ({} bytes): {e:?}", raw.len())); Defensive patterns
Strategy: validation
Validate before calling
let raw = collapse_bytes(&handle_output); assert!(!raw.is_empty(), "handler returned empty body"); // optionally check a leading marker/version byte if QueryResponse has one
Type guard
fn is_parsable_query_response(raw: &[u8]) -> bool {
QueryResponse::parse(raw.to_vec()).is_ok()
} Try / catch
let response = QueryResponse::parse(raw).unwrap_or_else(|e| {
panic!("QueryResponse parse failed ({:?}): {e:?}", &raw[..raw.len().min(32)])
}); Prevention
- Add round-trip tests (serialize -> parse) for QueryResponse on every format change.
- Assert handler output non-empty before parsing.
- Keep chunk-collapse helpers covered by their own unit tests.
When it happens
Trigger: run_request_handler returned bytes that QueryResponse::parse rejects: an empty Vec (e.g. a ClientIdentify-style early return), an error frame instead of a query result, or a QueryResponse serialized with a different op/version than the parser expects.
Common situations: Changing QueryResponse's serialization (field order, count prefix) without updating parse; the handler returned an empty result because the query matched nothing (store routing wrong); collapsing multi-chunk responses incorrectly in the test helper `collapse_bytes`.
Related errors
- handler failed
- get from local store should work
- Failed to create stores
- parsing a ClientIdentify request must succeed
- ClientIdentify must be handled successfully
AI-assisted analysis of EpicGames/lore@074eb0b0d1 (2026-09-13).
Data as JSON: /api/errors/a6f96e0944ed05d4.
Report an issue: GitHub.
Appendix: source
Thrown at lore-server/src/quic/replication_store_service/server.rs:1129
// ImmutableLocalQuery should find the data via the local store
let parse_output = service
.parse_request_bytes(
&CommandHeader::new(Command::ImmutableLocalQuery as QuicOpCode, 0, 0),
collapse_bytes_without_header(&request.clone().to_quic_chunks()),
)
.expect("Failed to parse");
assert!(matches!(
parse_output,
ParsedReplicationStoreRequest::Query(_)
));
let handle_output = service
.run_request_handler(AttributeMap::default().into(), parse_output)
.await
.expect("handler failed");
let response = QueryResponse::parse(collapse_bytes(&handle_output))
.expect("response parse should work");
assert_eq!(response.results[0].match_made, StoreMatch::MatchFull);
// ImmutableQuery should NOT find it (main store is empty)
let parse_output = service
.parse_request_bytes(
&CommandHeader::new(Command::ImmutableQuery as QuicOpCode, 0, 0),
collapse_bytes_without_header(&request.to_quic_chunks()),
)
.expect("Failed to parse");
let handle_output = service
.run_request_handler(AttributeMap::default().into(), parse_output)
.await
.expect("handler failed");
let response = QueryResponse::parse(collapse_bytes(&handle_output))
.expect("response parse should work");
assert_eq!(response.results[0].match_made, StoreMatch::MatchNone);
}View on GitHub (pinned to 074eb0b0d1)