cloudflare/cloudflared · error

Failed to suffix session ID to datagram, it will be dropped

Error message

Failed to suffix session ID to datagram, it will be dropped

What it means

In the QUIC datagram muxer (quic/datagram.go), SendToSession first rejects payloads larger than the transport MTU, then appends the session ID to the UDP payload via SuffixSessionID. If suffixing fails (session ID encoding/length problem), the datagram is dropped and this wrapped error is returned — the packet never reaches the edge.

Source

Thrown at quic/datagram.go:53

		session:   quicSession,
		logger:    &logger,
		demuxChan: demuxChan,
	}
}

// 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")

View on GitHub (pinned to 2253eeeb25)

Solutions

  1. Inspect the wrapped SuffixSessionID error to confirm whether the session ID or payload is at fault.
  2. Reduce the origin UDP payload size so it fits the MTU with room for the session ID suffix (the explicit MTU check above this code already guards payloads > mtu).
  3. Restart the affected UDP session to get a fresh, valid session ID if the ID appears corrupted.
  4. Ensure both cloudflared and the edge are on compatible versions (datagram protocol mismatches can corrupt session metadata).
Defensive patterns

Strategy: validation

Validate before calling

// enforce payload size before sending, leaving room for the session ID suffix
const maxUDPPayload = 1213 // stay below QUIC datagram MTU
if len(payload) > maxUDPPayload {
    return fmt.Errorf("UDP payload %d exceeds %d-byte limit", len(payload), maxUDPPayload)
}

Try / catch

if err := muxer.SendToSession(datagram); err != nil {
    if strings.Contains(err.Error(), "suffix session ID") {
        // recreate session: session ID state is suspect
        session = reopenSession(datagram.ID)
    }
    // UDP is best-effort: drop and continue
}

Prevention

When it happens

Trigger: SuffixSessionID(session.ID, session.Payload) returns an error, i.e. appending the session ID to the payload fails (malformed/oversized session ID relative to the datagram budget).

Common situations: Corrupted or incorrectly decoded session ID arriving from the edge demux path; UDP payload so close to the MTU that the appended session ID cannot fit within constraints enforced by the suffix helper.

Understand the failure class

Background: payload too large / request exceeds maximum size: why libraries cap bytes and how to fix oversize payloads — this error's family across 50 libraries.

Related errors


AI-assisted analysis of cloudflare/cloudflared@2253eeeb25 (2026-09-06). Data as JSON: /api/errors/7b124fb82fb4a251. Report an issue: GitHub.