{"record":{"id":"c39db7149fe4dc00","repo":"EpicGames/lore","slug":"failed-to-read-response","errorCode":null,"errorMessage":"Failed to read response","messagePattern":"Failed to read response","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"lore-server/src/quic/stream_handler.rs","lineNumber":858,"sourceCode":"                .await\n                .expect(\"Failed to open additional stream\")\n        }\n    }\n\n    /// Send a request asking the handler for `behaviour`.\n    async fn request(send: &mut SendStream, behaviour: MockBehaviour, command_id: u32) {\n        send.write(&CommandHeader::new(behaviour.opcode(), command_id, 0).to_bytes())\n            .await\n            .expect(\"Failed to write header\");\n        send.flush().await.expect(\"Failed flush\");\n    }\n\n    /// Read one response header.\n    async fn response(recv: &mut RecvStream) -> CommandHeader {\n        let mut buffer = [0u8; 8];\n        recv.read_exact(&mut buffer)\n            .await\n            .expect(\"Failed to read response\");\n        CommandHeader::from_bytes(&buffer)\n    }\n\n    /// Serve `factory` for `protocol` on a loopback endpoint and open a client stream to it.\n    ///\n    /// The client skips certificate verification and presents none of its own; the mTLS tests\n    /// build their endpoints by hand because varying exactly that is what they test.\n    async fn serve_and_connect(\n        factory: Box<dyn StreamHandlerFactory>,\n        protocol: &'static str,\n    ) -> Harness {\n        let socket = UdpSocket::bind(\"127.0.0.1:0\").unwrap();\n        let server_addr = socket.local_addr().expect(\"Failed socket setup\");\n        drop(socket);\n\n        let (cert_path, key_path, _) = server_certs().expect(\"Bad cert paths\");\n        let server = QuinnServer::start(\n            QuinnConfigBuilder::new()","sourceCodeStart":840,"sourceCodeEnd":876,"githubUrl":"https://github.com/EpicGames/lore/blob/074eb0b0d1194c997d7cf28b55519e3e197b3e23/lore-server/src/quic/stream_handler.rs#L840-L876","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nrecv.read_exact(&mut buffer).await.expect(\"Failed to read response\");\n// after\nrecv.read_exact(&mut buffer).await.unwrap_or_else(|e| panic!(\"Failed to read response: {:?}\", e));\n// and ensure the handler writes: send.write_all(&CommandHeader::new(...).to_bytes()).await?","handlingStrategy":"try-catch","validationCode":"// ensure the handler writes a response; on the server side:\n// send.write_all(&CommandHeader::new(...).to_bytes()).await?;","typeGuard":"fn got_full_header(n: usize) -> bool { n == 8 }","tryCatchPattern":"match recv.read_exact(&mut buffer).await {\n    Ok(()) => CommandHeader::from_bytes(&buffer),\n    Err(quinn::ReadExactError::FinishedEarly) => panic!(\"server ended stream before sending a full response header\"),\n    Err(quinn::ReadExactError::ReadError(e)) => panic!(\"Failed to read response: {e:?}\"),\n}","preventionTips":["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"],"tags":["quic","rust","test-harness","io"],"backgroundTag":"connection-closed","analyzedSha":"074eb0b0d1194c997d7cf28b55519e3e197b3e23","analyzedAt":"2026-09-13T09:00:57.509Z","contentChangedAt":"2026-09-13T09:00:57.509Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}