{"record":{"id":"25e7af16fdcdf416","repo":"cloudflare/quiche","slug":"error-closing-conn-e","errorCode":null,"errorMessage":"error closing conn: {e:?}","messagePattern":"error closing conn: (.+?)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"apps/src/common.rs","lineNumber":542,"sourceCode":"\n                    debug!(\n                        \"{}/{} responses received\",\n                        self.reqs_complete, reqs_count\n                    );\n\n                    if self.reqs_complete == reqs_count {\n                        info!(\n                            \"{}/{} response(s) received in {:?}, closing...\",\n                            self.reqs_complete,\n                            reqs_count,\n                            req_start.elapsed()\n                        );\n\n                        match conn.close(true, 0x00, b\"kthxbye\") {\n                            // Already closed.\n                            Ok(_) | Err(quiche::Error::Done) => (),\n\n                            Err(e) => panic!(\"error closing conn: {e:?}\"),\n                        }\n\n                        break;\n                    }\n                }\n            }\n        }\n    }\n\n    fn report_incomplete(&self, start: &std::time::Instant) -> bool {\n        if self.reqs_complete != self.reqs.len() {\n            error!(\n                \"connection timed out after {:?} and only completed {}/{} requests\",\n                start.elapsed(),\n                self.reqs_complete,\n                self.reqs.len()\n            );\n","sourceCodeStart":524,"sourceCodeEnd":560,"githubUrl":"https://github.com/cloudflare/quiche/blob/9f96daa2c22a4468b0036fb0a0a3894eee6498b8/apps/src/common.rs#L524-L560","documentation":"When the HTTP/0.9 response handling loop finishes, the client closes the connection with conn.close(true, 0x00, b\"kthxbye\") and panics if close returns an error other than Done. Done and Ok are treated as success (Done means already closed). Any other quiche::Error (e.g. InvalidState) indicates the connection is in an unexpected state at close time.","triggerScenarios":"Reaching the end of handle_responses while the underlying quiche::Connection is in a state where close() fails, e.g. after a fatal transport error already drained the connection.","commonSituations":"Connection already terminally errored or drained before the graceful close; race with peer-initiated close in lossy networks.","solutions":["Inspect the debug-formatted error in the message to identify the underlying quiche::Error.","Check earlier logs for transport errors that may have left the connection drained.","Treat this as a symptom: fix the root-cause connection failure first.","Update quiche if a state that should map to Done is being reported as an error."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Check connection state before attempting graceful close in client code\nif !conn.is_closed() && conn.is_drained() { /* skip close */ }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Treat this panic as a symptom of an earlier transport failure; review preceding errors.","Keep network paths healthy; heavy loss increases close-time races.","Track quiche updates for changes in close()/drained semantics."],"tags":["quic","connection-close","quiche-apps"],"backgroundTag":"invalid-state-transition","analyzedSha":"9f96daa2c22a4468b0036fb0a0a3894eee6498b8","analyzedAt":"2026-09-08T11:27:09.536Z","contentChangedAt":"2026-09-08T11:27:09.536Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}