XTLS/Xray-core · warning

failed to transport all UDP request

Error message

failed to transport all UDP request

What it means

Thrown when the UDP request relay (link.Reader → UDPWriter over the Shadowsocks connection) fails before completion. Each UDP packet is individually framed (address header + payload) and AEAD-encrypted; any write error on the underlying connection or packet encoding failure aborts the whole UDP session. Usually the network path to the server dropped or the conn was closed by the peer/context.

Source

Thrown at proxy/shadowsocks/client.go:167

		if err := task.Run(ctx, requestDone, responseDoneAndCloseWriter); err != nil {
			return errors.New("connection ends").Base(err)
		}

		return nil
	}

	if request.Command == protocol.RequestCommandUDP {

		requestDone := func() error {
			defer timer.SetTimeout(sessionPolicy.Timeouts.DownlinkOnly)

			writer := &UDPWriter{
				Writer:  conn,
				Request: request,
			}

			if err := buf.Copy(link.Reader, writer, buf.UpdateActivity(timer)); err != nil {
				return errors.New("failed to transport all UDP request").Base(err)
			}
			return nil
		}

		responseDone := func() error {
			defer timer.SetTimeout(sessionPolicy.Timeouts.UplinkOnly)

			reader := &UDPReader{
				Reader: conn,
				User:   user,
			}

			if err := buf.Copy(reader, link.Writer, buf.UpdateActivity(timer)); err != nil {
				return errors.New("failed to transport all UDP response").Base(err)
			}
			return nil
		}

View on GitHub (pinned to 7d214f8b09)

Solutions

  1. Confirm the server inbound has UDP enabled and the port is open for UDP (firewall allows UDP, not just TCP).
  2. Test with a simple DNS query through the proxy to isolate QUIC-specific throttling.
  3. If undesired, disable QUIC/UDP at the routing level (block quic or route UDP blackhole) so sessions do not half-fail.
  4. Check server logs for the same instant to see whether it intentionally closed the session.

Example fix

// before: routing lets all UDP through and the server blocks it
// after: sinkhole QUIC so only TCP is proxied
"routing": { "rules": [{ "network": "udp", "port": 443, "outboundTag": "block" }] }
Defensive patterns

Strategy: fallback

Try / catch

if err := buf.Copy(link.Reader, writer, buf.UpdateActivity(timer)); err != nil {
  if isConnClosed(err) {
    return nil // UDP flow ended; do not fail the whole session
  }
  return errors.New("failed to transport all UDP request").Base(err)
}

Prevention

When it happens

Trigger: Dispatching UDP (DNS, QUIC, WebRTC) through the Shadowsocks client where buf.Copy from the inbound link to the UDPWriter errors: server closed the UDP-capable conn, context canceled, or AEAD packet encode fails.

Common situations: Server does not actually support UDP on that port or blocks it; NAT rewrites making the server reject the session; QUIC-heavy traffic (HTTP/3) hitting servers that throttle UDP; client switches networks mid-session.

Related errors


AI-assisted analysis of XTLS/Xray-core@7d214f8b09 (2026-08-15). Data as JSON: /api/errors/4dd6d86d3354d84d. Report an issue: GitHub.