EpicGames/lore · error
Failed to read response
Error message
Failed to read response
What it means
This panic comes from response(): RecvStream::read_exact failed. read_exact returns Finished when the peer ended the stream before producing 8 header bytes, or an error when the connection is lost/reset — either way the full CommandHeader could not be read.
Solutions
- Confirm the server handler actually writes a full 8-byte CommandHeader for the given opcode
- Check server-side panics/logs for the MockBehaviour under test
- Verify CommandHeader serialization size still equals the 8-byte buffer the harness reads
- Distinguish Finished (early EOF, handler bug) from ConnectionLost (transport bug) in the ReadExactError
Example fix
// before
recv.read_exact(&mut buffer).await.expect("Failed to read response");
// after
recv.read_exact(&mut buffer).await.unwrap_or_else(|e| panic!("Failed to read response: {:?}", e));
// and ensure the handler writes: send.write_all(&CommandHeader::new(...).to_bytes()).await? Defensive patterns
Strategy: try-catch
Validate before calling
// ensure the handler writes a response; on the server side: // send.write_all(&CommandHeader::new(...).to_bytes()).await?;
Type guard
fn got_full_header(n: usize) -> bool { n == 8 } Try / catch
match recv.read_exact(&mut buffer).await {
Ok(()) => CommandHeader::from_bytes(&buffer),
Err(quinn::ReadExactError::FinishedEarly) => panic!("server ended stream before sending a full response header"),
Err(quinn::ReadExactError::ReadError(e)) => panic!("Failed to read response: {e:?}"),
} Prevention
- Verify the handler under test responds to every opcode the tests send
- Keep CommandHeader::to_bytes length equal to the harness's fixed 8-byte buffer
- Check server-side panic logs first when reads fail
- Distinguish FinishedEarly (handler bug) from transport errors
When it happens
Trigger: Server wrote fewer than 8 bytes (short/empty CommandHeader) then closed the stream; server never responded because the handler ignored the command; connection dropped mid-response.
Common situations: Handler implementation under test writes no response for the given opcode; handler panicked before writing a reply; response header serialization size changed so read_exact's fixed 8-byte buffer no longer matches.
Related errors
- Failed to write header
- Failed flush
- Failed to open additional stream
- Failed Quinn server start
- Failed to create client endpoint
AI-assisted analysis of EpicGames/lore@074eb0b0d1 (2026-09-13).
Data as JSON: /api/errors/c39db7149fe4dc00.
Report an issue: GitHub.
Appendix: source
Thrown at lore-server/src/quic/stream_handler.rs:858
.await
.expect("Failed to open additional stream")
}
}
/// Send a request asking the handler for `behaviour`.
async fn request(send: &mut SendStream, behaviour: MockBehaviour, command_id: u32) {
send.write(&CommandHeader::new(behaviour.opcode(), command_id, 0).to_bytes())
.await
.expect("Failed to write header");
send.flush().await.expect("Failed flush");
}
/// Read one response header.
async fn response(recv: &mut RecvStream) -> CommandHeader {
let mut buffer = [0u8; 8];
recv.read_exact(&mut buffer)
.await
.expect("Failed to read response");
CommandHeader::from_bytes(&buffer)
}
/// Serve `factory` for `protocol` on a loopback endpoint and open a client stream to it.
///
/// The client skips certificate verification and presents none of its own; the mTLS tests
/// build their endpoints by hand because varying exactly that is what they test.
async fn serve_and_connect(
factory: Box<dyn StreamHandlerFactory>,
protocol: &'static str,
) -> Harness {
let socket = UdpSocket::bind("127.0.0.1:0").unwrap();
let server_addr = socket.local_addr().expect("Failed socket setup");
drop(socket);
let (cert_path, key_path, _) = server_certs().expect("Bad cert paths");
let server = QuinnServer::start(
QuinnConfigBuilder::new()View on GitHub (pinned to 074eb0b0d1)