cloudflare/quiche · error
initial send failed
Error message
initial send failed
What it means
connect_with_early_data calls conn.send() to emit the ClientHello and panics if the initial packet write fails. conn.send() returns Err when there is nothing to send or the connection is in a state that cannot emit packets (e.g. already closed/drained, or internal crypto failure building the initial packet).
Solutions
- Ensure the connection is freshly created and not closed before connect_with_early_data is called.
- Verify TLS/ALPN configuration on the quiche::Config is valid.
- Replace the expect with proper error handling and retry or reconnect logic.
Example fix
// before
let (write, send_info) = conn.send(&mut out).expect("initial send failed");
// after
let (write, send_info) = conn.send(&mut out)
.map_err(|e| ClientError::Connect(format!("initial send failed: {e}")))?; Defensive patterns
Strategy: try-catch
Validate before calling
if conn.is_closed() || conn.is_draining() {
return Err(ClientError::Connect("connection already closed".into()));
} Try / catch
match conn.send(&mut out) {
Ok((w, info)) => (w, info),
Err(e) => return Err(ClientError::Connect(format!("initial send failed: {e}"))),
} Prevention
- Always use a freshly-created connection for connect().
- Verify TLS/ALPN config before connecting.
- Handle quiche errors instead of expect()ing in library-adjacent code.
When it happens
Trigger: The connection is done/drained before the first send, TLS setup failed so no ClientHello can be built, or the output buffer is too small/misallocated.
Common situations: Reusing a closed quiche::Connection; invalid TLS configuration (bad ALPN/CA setup) during client creation; extremely small send buffer in custom code paths.
Understand the failure class
Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.
Related errors
- Can't use RPK when compiled without rpk feature
- TimedOut
- initial send failed
- datagram extension not enabled by peer
- error closing conn
AI-assisted analysis of cloudflare/quiche@9f96daa2c2 (2026-09-08).
Data as JSON: /api/errors/e1011cc5a263ffe4.
Report an issue: GitHub.
Appendix: source
Thrown at h3i/src/client/sync_client.rs:219
if let Some(session) = &args.session {
conn.set_session(session)
.map_err(|error| ClientError::Other(error.to_string()))?;
}
if let Some(keylog) = &mut keylog {
if let Ok(keylog) = keylog.try_clone() {
conn.set_keylog(Box::new(keylog));
}
}
log::info!(
"connecting to {peer_addr:} from {local_addr:} with scid {scid:?}",
);
let mut app_proto_selected = false;
// Send ClientHello and initiate the handshake.
let (write, send_info) = conn.send(&mut out).expect("initial send failed");
let mut client = SyncClient::new(close_trigger_frames);
// Send early data if connection is_in_early_data (resumption with 0-RTT was
// successful) and if we have early_actions.
if conn.is_in_early_data() {
if let Some(early_actions) = early_actions {
let mut early_action_iter = early_actions.iter();
let mut wait_duration = None;
let mut wait_instant = None;
let mut waiting_for = WaitingFor::default();
check_duration_and_do_actions(
&mut wait_duration,
&mut wait_instant,
&mut early_action_iter,
&mut conn,
&mut waiting_for,
client.stream_parsers_mut(),View on GitHub (pinned to 9f96daa2c2)