{"record":{"id":"466c5366c50ffb0c","repo":"XTLS/Xray-core","slug":"uplinkdataplacement-can-be-only-in-packet-up-mode","errorCode":null,"errorMessage":"UplinkDataPlacement can be  only in packet-up mode","messagePattern":"UplinkDataPlacement can be  only in packet-up mode","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"infra/conf/transport_method.go","lineNumber":368,"sourceCode":"\tdefault:\n\t\treturn nil, errors.New(\"unsupported padding placement: \" + c.XPaddingPlacement)\n\t}\n\n\tswitch c.XPaddingMethod {\n\tcase \"\":\n\t\tc.XPaddingMethod = \"repeat-x\"\n\tcase \"repeat-x\", \"tokenish\":\n\tdefault:\n\t\treturn nil, errors.New(\"unsupported padding method: \" + c.XPaddingMethod)\n\t}\n\n\tswitch c.UplinkDataPlacement {\n\tcase \"\":\n\t\tc.UplinkDataPlacement = splithttp.PlacementAuto\n\tcase splithttp.PlacementAuto, splithttp.PlacementBody:\n\tcase splithttp.PlacementCookie, splithttp.PlacementHeader:\n\t\tif c.Mode != \"packet-up\" {\n\t\t\treturn nil, errors.New(\"UplinkDataPlacement can be \" + c.UplinkDataPlacement + \" only in packet-up mode\")\n\t\t}\n\tdefault:\n\t\treturn nil, errors.New(\"unsupported uplink data placement: \" + c.UplinkDataPlacement)\n\t}\n\n\tif c.UplinkHTTPMethod == \"\" {\n\t\tc.UplinkHTTPMethod = \"POST\"\n\t}\n\tc.UplinkHTTPMethod = strings.ToUpper(c.UplinkHTTPMethod)\n\n\tif c.UplinkHTTPMethod == \"GET\" && c.Mode != \"packet-up\" {\n\t\treturn nil, errors.New(\"uplinkHTTPMethod can be GET only in packet-up mode\")\n\t}\n\n\tswitch c.SessionIDPlacement {\n\tcase \"\":\n\t\tc.SessionIDPlacement = \"path\"\n\tcase \"path\", \"cookie\", \"header\", \"query\":","sourceCodeStart":350,"sourceCodeEnd":386,"githubUrl":"https://github.com/XTLS/Xray-core/blob/7d214f8b094f75322fa3990f8aadad1c912f24f5/infra/conf/transport_method.go#L350-L386","documentation":"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).","triggerScenarios":"\"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.","commonSituations":"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.","solutions":["Set \"mode\": \"packet-up\" when using \"uplinkDataPlacement\": \"cookie\" or \"header\"","Or change placement to \"auto\"/\"body\" for stream modes","Keep client and server mode/placement choices in sync — both ends must agree"],"exampleFix":"// before\n\"mode\": \"auto\", \"uplinkDataPlacement\": \"header\"\n// after\n\"mode\": \"packet-up\", \"uplinkDataPlacement\": \"header\"","handlingStrategy":"validation","validationCode":"// Go: cookie/header uplink placement requires packet-up mode\nmode := cfg.Mode\nif mode == \"\" {\n\tmode = \"auto\"\n}\nif cfg.UplinkDataPlacement == \"cookie\" || cfg.UplinkDataPlacement == \"header\" {\n\tif mode != \"packet-up\" {\n\t\treturn errors.New(\"set mode=packet-up or use auto/body placement\")\n\t}\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Pair cookie/header uplinkDataPlacement with packet-up mode","Default mode is auto — explicitly set packet-up when using these placements"],"tags":["config","splithttp","mode","uplink"],"backgroundTag":null,"analyzedSha":"7d214f8b094f75322fa3990f8aadad1c912f24f5","analyzedAt":"2026-08-15T14:26:24.325Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}