cloudflare/quiche · error
datagram extension not enabled by peer
Error message
datagram extension not enabled by peer
What it means
h3i's execute_action sends a QUIC datagram via conn.dgram_send() and panics with this message if the call returns an error. The QUIC datagram extension (RFC 9221) must be negotiated by both peers during the handshake; if the server did not advertise the DATAGRAM extension (or its max_datagram_frame_size is 0), sending fails and this expect() turns that into a panic.
Solutions
- Enable datagram support on the server (advertise max_datagram_frame_size, e.g. quiche Config.enable_dgram(true,..)).
- Remove the SendDatagram action from the h3i action file, or gate it on the peer's negotiated extensions.
- Check conn.dgram_send() result in h3i and surface a graceful error instead of panicking.
Example fix
// before (h3i action file)
{"action":"send_datagram","payload":"..."}
// after
{"action":"send_frame","stream_id":0,"frame":{"type":"settings",...}} // or enable datagrams on the server first Defensive patterns
Strategy: validation
Validate before calling
if !conn.dgram_max_writable_len().map_or(false, |l| l > 0) {
eprintln!("peer did not negotiate datagram extension; skipping SendDatagram");
return Ok(());
} Try / catch
// replace expect with error propagation
conn.dgram_send(payload).unwrap_or_else(|e| eprintln!("dgram_send failed: {e}")); Prevention
- Check conn.dgram_max_writable_len() > 0 before sending datagrams.
- Enable datagram support on both client and server configs.
- Gate SendDatagram actions behind a negotiated-extension check in action files.
When it happens
Trigger: Running an h3i action file containing a SendDatagram action against a server that did not negotiate the datagram extension, or before the handshake completed.
Common situations: Pointing h3i at a server without QUIC datagram support enabled; missing --enable-datagram / max_datagram_frame_size config on the peer; testing MASQUE/CONNECT-UDP against a plain HTTP/3 server.
Related errors
- initial send failed
- initial send failed
- error closing conn
- The provided buffer is too large
- tokio task ID already in use
AI-assisted analysis of cloudflare/quiche@9f96daa2c2 (2026-09-08).
Data as JSON: /api/errors/f29b799dfb4ed83f.
Report an issue: GitHub.
Appendix: source
Thrown at h3i/src/client/mod.rs:303
log::info!(
"stream bytes tx id={} len={} fin={}",
stream_id,
bytes.len(),
fin_stream
);
let result = conn.stream_send(*stream_id, bytes, *fin_stream);
validate_stream_send_result(result, expected_result, *stream_id);
stream_parsers
.entry(*stream_id)
.or_insert_with(|| FrameParser::new(*stream_id));
},
Action::SendDatagram { payload } => {
log::info!("dgram tx len={}", payload.len(),);
conn.dgram_send(payload)
.expect("datagram extension not enabled by peer");
},
Action::ResetStream {
stream_id,
error_code,
} => {
log::info!(
"reset_stream stream_id={stream_id} error_code={error_code}"
);
if let Err(e) = conn.stream_shutdown(
*stream_id,
quiche::Shutdown::Write,
*error_code,
) {
log::error!("can't send reset_stream: {e}");
// Clients cannot reset streams they do not own. If attempted,
// `stream_shutdown()` fails and no parser should be created.
return;View on GitHub (pinned to 9f96daa2c2)