{"record":{"id":"8008453b6b47a742","repo":"cloudflare/cloudflared","slug":"failed-to-suffix-session-id-to-datagram-it-will-b-800845","errorCode":null,"errorMessage":"Failed to suffix session ID to datagram, it will be dropped","messagePattern":"Failed to suffix session ID to datagram, it will be dropped","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"quic/datagramv2.go","lineNumber":82,"sourceCode":"\tlogger := log.With().Uint8(\"datagramVersion\", 2).Logger()\n\treturn &DatagramMuxerV2{\n\t\tsession:          quicSession,\n\t\tlogger:           &logger,\n\t\tsessionDemuxChan: sessionDemuxChan,\n\t\tpacketDemuxChan:  make(chan Packet, packetChanCapacity),\n\t}\n}\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","sourceCodeStart":64,"sourceCodeEnd":100,"githubUrl":"https://github.com/cloudflare/cloudflared/blob/2253eeeb25a44a713a4b60b8ba1e1b3f377d1a0f/quic/datagramv2.go#L64-L100","documentation":"Same family as the datagram v1 case but in quic/datagramv2.go: SendToSession rejects oversized payloads, then appends the session ID via SuffixSessionID. If suffixing the session ID fails, the datagram is dropped and wrapped with this message. Version 2 additionally suffixes a datagram type byte afterwards.","triggerScenarios":"SuffixSessionID(session.ID, session.Payload) errors during a v2-protocol UDP datagram send — malformed or unencodable session ID, or payload/session-ID combination exceeding suffix constraints.","commonSituations":"Protocol mismatch between cloudflared and edge datagram versions corrupting session metadata; near-MTU UDP payloads; corrupted session state after reconnect.","solutions":["Read the wrapped SuffixSessionID cause to identify which component (ID vs payload) failed.","Shrink the origin UDP payload to leave headroom below the MTU for the ID and type suffixes.","Restart the UDP session / cloudflared to re-establish clean session state.","Verify cloudflared and edge support the same datagram v2 protocol; try --protocol quic vs auto to pin behavior."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// enforce a conservative payload cap covering session ID + type suffixes\nconst maxUDPPayloadV2 = 1200\nif len(payload) > maxUDPPayloadV2 {\n    return fmt.Errorf(\"payload %d too large for datagram v2\", len(payload))\n}","typeGuard":null,"tryCatchPattern":"if err := muxer.SendToSession(datagram); err != nil {\n    if strings.Contains(err.Error(), \"suffix session ID\") {\n        log.Warn().Str(\"session\", datagram.ID).Msg(\"dropping datagram: bad session id\")\n        resetSession(datagram.ID)\n    }\n    return err\n}","preventionTips":["Keep UDP payloads well under the MTU to leave room for v2 suffixes.","Run matching cloudflared/edge protocol versions; avoid stale clients.","Reset UDP sessions after reconnects to avoid corrupted session metadata.","Track drop metrics per session to catch persistent ID corruption early."],"tags":["quic","udp","datagramv2","packet-drop"],"backgroundTag":"payload-too-large","analyzedSha":"2253eeeb25a44a713a4b60b8ba1e1b3f377d1a0f","analyzedAt":"2026-09-06T04:14:33.757Z","contentChangedAt":"2026-09-06T04:14:33.757Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}