{"record":{"id":"b01bc85356bc0d72","repo":"cloudflare/quiche","slug":"initial-send-failed","errorCode":null,"errorMessage":"initial send failed","messagePattern":"initial send failed","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"apps/src/client.rs","lineNumber":232,"sourceCode":"                format!(\"{} id={}\", \"quiche-client qlog\", id),\n            );\n        }\n    }\n\n    if let Some(session_file) = &args.session_file {\n        if let Ok(session) = std::fs::read(session_file) {\n            conn.set_session(&session).ok();\n        }\n    }\n\n    info!(\n        \"connecting to {:} from {:} with scid {:?}\",\n        peer_addr,\n        socket.local_addr().unwrap(),\n        scid,\n    );\n\n    let (write, send_info) = conn.send(&mut out).expect(\"initial send failed\");\n\n    while let Err(e) = socket.send_to(&out[..write], send_info.to) {\n        if e.kind() == std::io::ErrorKind::WouldBlock {\n            trace!(\n                \"{} -> {}: send() would block\",\n                socket.local_addr().unwrap(),\n                send_info.to\n            );\n            continue;\n        }\n\n        return Err(ClientError::Other(format!(\"send() failed: {e:?}\")));\n    }\n\n    trace!(\"written {write}\");\n\n    let app_data_start = std::time::Instant::now();\n","sourceCodeStart":214,"sourceCodeEnd":250,"githubUrl":"https://github.com/cloudflare/quiche/blob/9f96daa2c22a4468b0036fb0a0a3894eee6498b8/apps/src/client.rs#L214-L250","documentation":"In quiche-client's connect(), the very first packet sent (the QUIC initial) is produced by conn.send() and unwrapped with expect(\"initial send failed\"). If the connection cannot encode the initial packet (e.g. the connection is already in an error/done state), the client panics with this message.","triggerScenarios":"conn.send(&mut out) returns Err on the first send attempt after connection creation — typically because the connection state rejects generating an initial packet (connection already closed/done, config issue).","commonSituations":"Extremely small send buffer (out) too short for the initial packet plus TLS data; connection immediately closed due to invalid config (bad TLS cert/key, invalid local address); QUIC version mismatches causing early close.","solutions":["Ensure the `out` buffer is at least MAX_DATAGRAM_SIZE and quiche's MIN_CLIENT_INITIAL_LEN is respected","Verify TLS certificate/key files load correctly before connect","Check the log/trace output for the underlying quiche error to see why the initial couldn't be produced","Replace the expect with proper error handling if embedding this code"],"exampleFix":"// before\nlet (write, send_info) = conn.send(&mut out).expect(\"initial send failed\");\n// after\nlet (write, send_info) = match conn.send(&mut out) {\n    Ok(v) => v,\n    Err(e) => { eprintln!(\"initial send failed: {e}\"); return Err(e.into()); }\n};","handlingStrategy":"try-catch","validationCode":"assert!(out.len() >= quiche::MAX_DATAGRAM_SIZE);\nassert!(conn.is_established() || !conn.is_closed());","typeGuard":null,"tryCatchPattern":"let (write, send_info) = conn.send(&mut out)\n    .map_err(|e| anyhow!(\"initial send failed: {e}\"))?;","preventionTips":["Size the send buffer at least MAX_DATAGRAM_SIZE and respect MIN_CLIENT_INITIAL_LEN","Verify TLS cert/key load before creating the connection","Log the underlying quiche::Error instead of panicking with expect"],"tags":["quic","quiche-client","panic","initial-packet"],"backgroundTag":"internal-invariant-violation","analyzedSha":"9f96daa2c22a4468b0036fb0a0a3894eee6498b8","analyzedAt":"2026-09-08T11:27:09.536Z","contentChangedAt":"2026-09-08T11:27:09.536Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}