cloudflare/cloudflared · error
Failed to send datagram back to edge
Error message
Failed to send datagram back to edge
What it means
In quic/datagramv2.go SendToSession, once the payload carries the session ID and type byte, dm.session.SendDatagram(msgWithIDAndType) transmits it to Cloudflare's edge. An error here means the QUIC connection could not accept the datagram, and the UDP packet is dropped.
Source
Thrown at quic/datagramv2.go:89
}
// SendToSession suffix the session ID and datagram version to the payload so the other end of the QUIC connection can
// demultiplex the payload from multiple datagram sessions
func (dm *DatagramMuxerV2) 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())
}
msgWithID, err := SuffixSessionID(session.ID, session.Payload)
if err != nil {
return errors.Wrap(err, "Failed to suffix session ID to datagram, it will be dropped")
}
msgWithIDAndType, err := SuffixType(msgWithID, DatagramTypeUDP)
if err != nil {
return errors.Wrap(err, "Failed to suffix datagram type, it will be dropped")
}
if err := dm.session.SendDatagram(msgWithIDAndType); err != nil {
return errors.Wrap(err, "Failed to send datagram back to edge")
}
return nil
}
// SendPacket sends a packet with datagram version in the suffix. If ctx is a TracedContext, it adds the tracing
// context between payload and datagram version.
// The other end of the QUIC connection can demultiplex by parsing the payload as IP and look at the source and destination.
func (dm *DatagramMuxerV2) SendPacket(pk Packet) error {
payloadWithMetadata, err := suffixMetadata(pk.Payload(), pk.Metadata())
if err != nil {
return err
}
payloadWithMetadataAndType, err := SuffixType(payloadWithMetadata, pk.Type())
if err != nil {
return errors.Wrap(err, "Failed to suffix datagram type, it will be dropped")
}
if err := dm.session.SendDatagram(payloadWithMetadataAndType); err != nil {
return errors.Wrap(err, "Failed to send datagram back to edge")View on GitHub (pinned to 2253eeeb25)
Solutions
- Check tunnel health/logs for QUIC reconnects; transient errors resolve after reconnection.
- Retry at the application layer — UDP over the tunnel tolerates loss.
- Throttle UDP traffic if the send queue is overflowing.
- Switch protocol (--protocol http2) or upgrade cloudflared if QUIC datagram failures are persistent on your network path.
Defensive patterns
Strategy: retry
Validate before calling
select {
case <-muxer.Ready(): // connection available
return muxer.SendToSession(datagram)
default:
return errors.New("datagram muxer not connected to edge")
} Try / catch
err := muxer.SendToSession(datagram)
if err != nil && strings.Contains(err.Error(), "send datagram back to edge") {
// bounded retry with backoff during edge reconnects
return retryWithBackoff(3, 100*time.Millisecond, func() error {
return muxer.SendToSession(datagram)
})
} Prevention
- Expect loss during QUIC reconnects; buffer or replay critical datagrams at the app layer.
- Watch for send-queue saturation and throttle bursty UDP senders.
- Keep cloudflared supervised (auto-restart) so reconnects recover quickly.
- Consider --protocol http2 fallback on networks with unstable UDP paths.
When it happens
Trigger: dm.session.SendDatagram returns an error during a v2 datagram send — QUIC connection closed/reconnecting, or the datagram send queue is full.
Common situations: Edge connection drop or handshake in progress; sustained UDP traffic exceeding datagram throughput (queue backpressure); cloudflared shutdown while UDP sessions persist.
Related errors
- Failed to send datagram back to edge
- Failed to suffix session ID to datagram, it will be dropped
- Failed to suffix datagram type, it will be dropped
- Failed to suffix session ID to datagram, it will be dropped
- invalid datagram type expected
AI-assisted analysis of cloudflare/cloudflared@2253eeeb25 (2026-09-06).
Data as JSON: /api/errors/2b70205aec9cb4bd.
Report an issue: GitHub.