{"record":{"id":"2b70205aec9cb4bd","repo":"cloudflare/cloudflared","slug":"failed-to-send-datagram-back-to-edge-2b7020","errorCode":null,"errorMessage":"Failed to send datagram back to edge","messagePattern":"Failed to send datagram back to edge","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"quic/datagramv2.go","lineNumber":89,"sourceCode":"}\n\n// SendToSession suffix the session ID and datagram version to the payload so the other end of the QUIC connection can\n// demultiplex the payload from multiple datagram sessions\nfunc (dm *DatagramMuxerV2) SendToSession(session *packet.Session) error {\n\tif len(session.Payload) > dm.mtu() {\n\t\tpacketTooBigDropped.Inc()\n\t\treturn fmt.Errorf(\"origin UDP payload has %d bytes, which exceeds transport MTU %d\", len(session.Payload), dm.mtu())\n\t}\n\tmsgWithID, err := SuffixSessionID(session.ID, session.Payload)\n\tif err != nil {\n\t\treturn errors.Wrap(err, \"Failed to suffix session ID to datagram, it will be dropped\")\n\t}\n\tmsgWithIDAndType, err := SuffixType(msgWithID, DatagramTypeUDP)\n\tif err != nil {\n\t\treturn errors.Wrap(err, \"Failed to suffix datagram type, it will be dropped\")\n\t}\n\tif err := dm.session.SendDatagram(msgWithIDAndType); err != nil {\n\t\treturn errors.Wrap(err, \"Failed to send datagram back to edge\")\n\t}\n\treturn nil\n}\n\n// SendPacket sends a packet with datagram version in the suffix. If ctx is a TracedContext, it adds the tracing\n// context between payload and datagram version.\n// The other end of the QUIC connection can demultiplex by parsing the payload as IP and look at the source and destination.\nfunc (dm *DatagramMuxerV2) SendPacket(pk Packet) error {\n\tpayloadWithMetadata, err := suffixMetadata(pk.Payload(), pk.Metadata())\n\tif err != nil {\n\t\treturn err\n\t}\n\tpayloadWithMetadataAndType, err := SuffixType(payloadWithMetadata, pk.Type())\n\tif err != nil {\n\t\treturn errors.Wrap(err, \"Failed to suffix datagram type, it will be dropped\")\n\t}\n\tif err := dm.session.SendDatagram(payloadWithMetadataAndType); err != nil {\n\t\treturn errors.Wrap(err, \"Failed to send datagram back to edge\")","sourceCodeStart":71,"sourceCodeEnd":107,"githubUrl":"https://github.com/cloudflare/cloudflared/blob/2253eeeb25a44a713a4b60b8ba1e1b3f377d1a0f/quic/datagramv2.go#L71-L107","documentation":"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.","triggerScenarios":"dm.session.SendDatagram returns an error during a v2 datagram send — QUIC connection closed/reconnecting, or the datagram send queue is full.","commonSituations":"Edge connection drop or handshake in progress; sustained UDP traffic exceeding datagram throughput (queue backpressure); cloudflared shutdown while UDP sessions persist.","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."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"select {\ncase <-muxer.Ready(): // connection available\n    return muxer.SendToSession(datagram)\ndefault:\n    return errors.New(\"datagram muxer not connected to edge\")\n}","typeGuard":null,"tryCatchPattern":"err := muxer.SendToSession(datagram)\nif err != nil && strings.Contains(err.Error(), \"send datagram back to edge\") {\n    // bounded retry with backoff during edge reconnects\n    return retryWithBackoff(3, 100*time.Millisecond, func() error {\n        return muxer.SendToSession(datagram)\n    })\n}","preventionTips":["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."],"tags":["quic","udp","datagramv2","edge","packet-drop"],"backgroundTag":"network-request-failed","analyzedSha":"2253eeeb25a44a713a4b60b8ba1e1b3f377d1a0f","analyzedAt":"2026-09-06T04:14:33.757Z","contentChangedAt":"2026-09-06T04:14:33.757Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}