XTLS/Xray-core · error

UplinkDataPlacement can be only in packet-up mode

Error message

UplinkDataPlacement can be  only in packet-up mode

What it means

SplitHTTPConfig.Build() restricts uplink data placement to the request body except in packet-up mode, at transport_method.go:362-369. Placing raw packet data in a cookie or header is only meaningful when each uplink HTTP request carries one packet ("packet-up" mode); in "auto"/"stream-up"/"stream-one" the data is a continuous stream and must go in the body (PlacementAuto/PlacementBody). The message interpolates c.UplinkDataPlacement (appears empty when the constant's string value is blank in the rendered message).

Source

Thrown at infra/conf/transport_method.go:368

	default:
		return nil, errors.New("unsupported padding placement: " + c.XPaddingPlacement)
	}

	switch c.XPaddingMethod {
	case "":
		c.XPaddingMethod = "repeat-x"
	case "repeat-x", "tokenish":
	default:
		return nil, errors.New("unsupported padding method: " + c.XPaddingMethod)
	}

	switch c.UplinkDataPlacement {
	case "":
		c.UplinkDataPlacement = splithttp.PlacementAuto
	case splithttp.PlacementAuto, splithttp.PlacementBody:
	case splithttp.PlacementCookie, splithttp.PlacementHeader:
		if c.Mode != "packet-up" {
			return nil, errors.New("UplinkDataPlacement can be " + c.UplinkDataPlacement + " only in packet-up mode")
		}
	default:
		return nil, errors.New("unsupported uplink data placement: " + c.UplinkDataPlacement)
	}

	if c.UplinkHTTPMethod == "" {
		c.UplinkHTTPMethod = "POST"
	}
	c.UplinkHTTPMethod = strings.ToUpper(c.UplinkHTTPMethod)

	if c.UplinkHTTPMethod == "GET" && c.Mode != "packet-up" {
		return nil, errors.New("uplinkHTTPMethod can be GET only in packet-up mode")
	}

	switch c.SessionIDPlacement {
	case "":
		c.SessionIDPlacement = "path"
	case "path", "cookie", "header", "query":

View on GitHub (pinned to 7d214f8b09)

Solutions

  1. Set "mode": "packet-up" when using "uplinkDataPlacement": "cookie" or "header"
  2. Or change placement to "auto"/"body" for stream modes
  3. Keep client and server mode/placement choices in sync — both ends must agree

Example fix

// before
"mode": "auto", "uplinkDataPlacement": "header"
// after
"mode": "packet-up", "uplinkDataPlacement": "header"
Defensive patterns

Strategy: validation

Validate before calling

// Go: cookie/header uplink placement requires packet-up mode
mode := cfg.Mode
if mode == "" {
	mode = "auto"
}
if cfg.UplinkDataPlacement == "cookie" || cfg.UplinkDataPlacement == "header" {
	if mode != "packet-up" {
		return errors.New("set mode=packet-up or use auto/body placement")
	}
}

Prevention

When it happens

Trigger: "uplinkDataPlacement": "cookie" or "header" together with "mode": "auto" (or "stream-up"/"stream-one", or mode omitted — default is auto). Placement "auto" and "body" never trigger it.

Common situations: Copying a tuned packet-up client config but changing/removing the mode line; server-side config reuse where mode was not updated in sync; mixing examples from different guides.

Related errors


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