cloudflare/cloudflared · error
Failed to send datagram back to edge
Error message
Failed to send datagram back to edge
What it means
In quic/datagram.go SendToSession, after the session ID is successfully suffixed, the payload is handed to dm.session.SendDatagram to ship over the QUIC connection to Cloudflare's edge. Failure here means the QUIC connection itself refused or could not queue the datagram, and the UDP packet is lost.
Source
Thrown at quic/datagram.go:56
}
}
// Maximum application payload to send to / receive from QUIC datagram frame
func (dm *DatagramMuxer) mtu() int {
return maxDatagramPayloadSize
}
func (dm *DatagramMuxer) SendToSession(session *packet.Session) error {
if len(session.Payload) > dm.mtu() {
packetTooBigDropped.Inc()
return fmt.Errorf("origin UDP payload has %d bytes, which exceeds transport MTU %d", len(session.Payload), dm.mtu())
}
payloadWithMetadata, err := SuffixSessionID(session.ID, session.Payload)
if err != nil {
return errors.Wrap(err, "Failed to suffix session ID to datagram, it will be dropped")
}
if err := dm.session.SendDatagram(payloadWithMetadata); err != nil {
return errors.Wrap(err, "Failed to send datagram back to edge")
}
return nil
}
func (dm *DatagramMuxer) ServeReceive(ctx context.Context) error {
for {
// Extracts datagram session ID, then sends the session ID and payload to receiver
// which determines how to proxy to the origin. It assumes the datagram session has already been
// registered with receiver through other side channel
msg, err := dm.session.ReceiveDatagram(ctx)
if err != nil {
return err
}
if err := dm.demux(ctx, msg); err != nil {
dm.logger.Error().Err(err).Msg("Failed to demux datagram")
if err == context.Canceled {
return err
}View on GitHub (pinned to 2253eeeb25)
Solutions
- Confirm the tunnel is connected (cloudflared metrics/logs for reconnect events); the error is usually transient during reconnects.
- Retry the UDP exchange from the client — UDP under cloudflared is lossy by design; applications must tolerate drops.
- Reduce UDP send rate if the datagram queue is overflowing (backpressure from a traffic burst).
- If persistent, check MTU/UDP path issues between cloudflared and the edge that could break the QUIC connection, or fall back to the http2 protocol (--protocol http2).
Defensive patterns
Strategy: retry
Validate before calling
// check tunnel connectivity before streaming UDP
if !tunnelConnected() {
return errors.New("tunnel to edge is down; defer UDP sends")
} Try / catch
if err := muxer.SendToSession(datagram); err != nil {
if strings.Contains(err.Error(), "send datagram back to edge") {
select {
case <-time.After(50 * time.Millisecond):
return retrySend(datagram) // transient edge disconnect
case <-ctx.Done():
return ctx.Err()
}
}
return err
} Prevention
- Design UDP applications to tolerate packet loss — the tunnel does not guarantee delivery.
- Monitor QUIC reconnect events in cloudflared logs/metrics.
- Rate-limit UDP bursts so the datagram send queue does not overflow.
- Test with --protocol http2 if your network path destabilizes QUIC.
When it happens
Trigger: dm.session.SendDatagram(payloadWithMetadata) returns an error — QUIC connection closed, datagram queue full (flow control/backpressure), or the connection is shutting down.
Common situations: Tunnel to edge temporarily disconnected or reconnecting; QUIC datagram send queue overflowed during a UDP traffic burst; cloudflared shutting down while UDP sessions are still active.
Related errors
- Failed to suffix session ID to datagram, it will be dropped
- Failed to send datagram back to edge
- invalid datagram type expected
- Failed to suffix session ID to datagram, it will be dropped
- Failed to suffix datagram type, it will be dropped
AI-assisted analysis of cloudflare/cloudflared@2253eeeb25 (2026-09-06).
Data as JSON: /api/errors/c4e8babf0b01d772.
Report an issue: GitHub.