{"record":{"id":"091dff1d0b719ed4","repo":"EpicGames/lore","slug":"failed-flush","errorCode":null,"errorMessage":"Failed flush","messagePattern":"Failed flush","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"lore-server/src/quic/stream_handler.rs","lineNumber":850,"sourceCode":"        _endpoint: Endpoint,\n    }\n\n    impl Harness {\n        /// Open an additional stream on the same connection.\n        async fn open_stream(&self) -> (SendStream, RecvStream) {\n            self.connection\n                .open_bi()\n                .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,","sourceCodeStart":832,"sourceCodeEnd":868,"githubUrl":"https://github.com/EpicGames/lore/blob/074eb0b0d1194c997d7cf28b55519e3e197b3e23/lore-server/src/quic/stream_handler.rs#L832-L868","documentation":"This panic comes from request(): SendStream::flush returned Err. flush() waits for all buffered stream data to be acked-schedulable and fails under the same conditions as write — closed stream or dead connection.","triggerScenarios":"flush() after the peer stopped the stream, after connection close, or when the connection was lost between write() and flush().","commonSituations":"Server closed the connection immediately after reading the header so the flush wait fails; handler panicked between header read and processing; QUIC connection idle timeout fired during the flush await.","solutions":["Check for a close race: the handler finishing/closing right after consuming the header","Verify the WriteError/CallDisconnect reason to distinguish ClosedStream from ConnectionLost","Keep the server alive for the duration of the test (hold the QuinnServer handle, as Harness does with _server)","If the race is inherent, downgrade flush to a best-effort match on ClosedStream"],"exampleFix":"// before\nsend.flush().await.expect(\"Failed flush\");\n// after\nif let Err(e) = send.flush().await {\n    panic!(\"Failed flush: {:?} (connection reason: {:?})\", e, connection.close_reason());\n}","handlingStrategy":"try-catch","validationCode":"// before flush, confirm connection is alive\nif connection.close_reason().is_some() { panic!(\"connection closed before flush\"); }","typeGuard":"fn conn_open(conn: &quinn::Connection) -> bool { conn.close_reason().is_none() }","tryCatchPattern":"if let Err(quinn::WriteError::ClosedStream) = send.flush().await {\n    // benign race: handler closed the stream right after consuming the header\n} else if let Err(e) = send.flush().await {\n    panic!(\"Failed flush: {e:?}\");\n}","preventionTips":["Treat ClosedStream on flush as a possible benign race in request/response helpers","Check the handler hasn't closed the connection concurrently","Avoid long gaps between write and flush to dodge idle timeouts"],"tags":["quic","rust","test-harness","io"],"backgroundTag":"broken-pipe","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"}