{"record":{"id":"2269a03d3ce6b361","repo":"EpicGames/lore","slug":"failed-to-open-additional-stream","errorCode":null,"errorMessage":"Failed to open additional stream","messagePattern":"Failed to open additional stream","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"lore-server/src/quic/stream_handler.rs","lineNumber":841,"sourceCode":"    ///\n    /// Quinn's send and receive streams cannot be mocked, so exercising the stream handler needs\n    /// a real server. The server, endpoint and connection are held because dropping any of them\n    /// closes the stream.\n    struct Harness {\n        send: SendStream,\n        recv: RecvStream,\n        connection: quinn::Connection,\n        _server: QuinnServer,\n        _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)","sourceCodeStart":823,"sourceCodeEnd":859,"githubUrl":"https://github.com/EpicGames/lore/blob/074eb0b0d1194c997d7cf28b55519e3e197b3e23/lore-server/src/quic/stream_handler.rs#L823-L859","documentation":"This is a test-helper panic in Harness::open_stream: quinn's connection.open_bi() returned an Err (or the await was cancelled by connection death), and the test harness unwraps it with this message. It means the QUIC connection could not allocate a new bidirectional stream — almost always because the connection has already been closed or the peer refused the stream.","triggerScenarios":"Calling open_bi() after the server dropped the connection, after an idle timeout, when the peer's MAX_STREAMS credit is exhausted, or after connection.close()/QuinnServer::start failed so no connection was ever established.","commonSituations":"Server handler panicked and killed the connection before the test opened a second stream; ALPN mismatch or certificate rejection closed the connection during handshake; idle timeout between test steps; stream-count limits hit after many open_stream calls.","solutions":["Check the server-side handler/factory for panics or early connection.close() before open_bi is called","Ensure the client connection is still alive: inspect connection.close_reason() before opening streams","Verify ALPN protocol strings match between server QuinnConfigBuilder and client crypto_config.alpn_protocols","Reduce open_stream calls or confirm MAX_STREAMS transport limits permit another bidirectional stream"],"exampleFix":"// before\nself.connection.open_bi().await.expect(\"Failed to open additional stream\")\n// after\nmatch self.connection.open_bi().await {\n    Ok(pair) => pair,\n    Err(e) => panic!(\"Failed to open additional stream: {:?} (close reason: {:?})\", e, self.connection.close_reason()),\n}","handlingStrategy":"try-catch","validationCode":"// before calling open_stream\nif harness.connection.close_reason().is_some() {\n    panic!(\"connection already closed: {:?}\", harness.connection.close_reason());\n}","typeGuard":"fn is_conn_alive(conn: &quinn::Connection) -> bool { conn.close_reason().is_none() }","tryCatchPattern":"match self.connection.open_bi().await {\n    Ok((s, r)) => (s, r),\n    Err(quinn::ConnectionError::Closed(_) | quinn::ConnectionError::LocallyClosed) => panic!(\"connection closed before open_bi\"),\n    Err(e) => panic!(\"Failed to open additional stream: {e:?}\"),\n}","preventionTips":["Check close_reason() before opening streams in tests","Assert the server handler survived (no panic) before client-side stream operations","Verify ALPN strings are identical constants shared by client and server","Watch MAX_STREAMS limits in long-running loop tests"],"tags":["quic","rust","test-harness","stream"],"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"}