{"record":{"id":"4465aa567b20ab06","repo":"XTLS/Xray-core","slug":"failed-to-fallback-request-payload","errorCode":null,"errorMessage":"failed to fallback request payload","messagePattern":"failed to fallback request payload","errorType":"console","errorClass":null,"httpStatus":null,"severity":"info","filePath":"proxy/trojan/server.go","lineNumber":527,"sourceCode":"\t\t\t\tif ipType == 4 {\n\t\t\t\t\tcommon.Must2(pro.Write([]byte(\"\\x21\\x11\\x00\\x0C\"))) // v2 + PROXY + AF_INET + STREAM + 12 bytes\n\t\t\t\t\tcommon.Must2(pro.Write(net.ParseIP(remoteAddr).To4()))\n\t\t\t\t\tcommon.Must2(pro.Write(net.ParseIP(localAddr).To4()))\n\t\t\t\t} else {\n\t\t\t\t\tcommon.Must2(pro.Write([]byte(\"\\x21\\x21\\x00\\x24\"))) // v2 + PROXY + AF_INET6 + STREAM + 36 bytes\n\t\t\t\t\tcommon.Must2(pro.Write(net.ParseIP(remoteAddr).To16()))\n\t\t\t\t\tcommon.Must2(pro.Write(net.ParseIP(localAddr).To16()))\n\t\t\t\t}\n\t\t\t\tp1, _ := strconv.ParseUint(remotePort, 10, 16)\n\t\t\t\tp2, _ := strconv.ParseUint(localPort, 10, 16)\n\t\t\t\tcommon.Must2(pro.Write([]byte{byte(p1 >> 8), byte(p1), byte(p2 >> 8), byte(p2)}))\n\t\t\t}\n\t\t\tif err := serverWriter.WriteMultiBuffer(buf.MultiBuffer{pro}); err != nil {\n\t\t\t\treturn errors.New(\"failed to set PROXY protocol v\", fb.Xver).Base(err).AtWarning()\n\t\t\t}\n\t\t}\n\t\tif err := buf.Copy(reader, serverWriter, buf.UpdateActivity(timer)); err != nil {\n\t\t\treturn errors.New(\"failed to fallback request payload\").Base(err).AtInfo()\n\t\t}\n\t\treturn nil\n\t}\n\n\twriter := buf.NewWriter(connection)\n\n\tgetResponse := func() error {\n\t\tdefer timer.SetTimeout(sessionPolicy.Timeouts.UplinkOnly)\n\t\tif err := buf.Copy(serverReader, writer, buf.UpdateActivity(timer)); err != nil {\n\t\t\treturn errors.New(\"failed to deliver response payload\").Base(err).AtInfo()\n\t\t}\n\t\treturn nil\n\t}\n\n\tif err := task.Run(ctx, task.OnSuccess(postRequest, task.Close(serverWriter)), task.OnSuccess(getResponse, task.Close(writer))); err != nil {\n\t\tcommon.Must(common.Interrupt(serverReader))\n\t\tcommon.Must(common.Interrupt(serverWriter))\n\t\treturn errors.New(\"fallback ends\").Base(err).AtInfo()","sourceCodeStart":509,"sourceCodeEnd":545,"githubUrl":"https://github.com/XTLS/Xray-core/blob/7d214f8b094f75322fa3990f8aadad1c912f24f5/proxy/trojan/server.go#L509-L545","documentation":"Uplink copy from the trojan client to the fallback backend failed (buf.Copy reader→serverWriter) during fallback relaying. AtInfo severity: fallback traffic is best-effort camouflage of already-rejected trojan traffic, so failures are informational.","triggerScenarios":"Client disconnects mid-fallback, backend closes early (it already got enough bytes to respond, e.g. a 400), or the idle timer cancels the context.","commonSituations":"Scanners/probers that half-close after sending a request; backend rejecting garbage with an immediate close.","solutions":["Usually no action: verify the backend responded as intended","If backends close immediately, review whether they expect PROXY protocol (see [731])","Ignore unless fallback traffic genuinely needs relay fidelity"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"if err := buf.Copy(reader, serverWriter, buf.UpdateActivity(timer)); err != nil {\n    // best-effort fallback uplink; failure just ends the fallback relay\n    return errors.New(\"failed to fallback request payload\").Base(err).AtInfo()\n}","preventionTips":["Do not build retry logic on fallback pipes; they are camouflage, not transport","Keep the fallback backend's accept behavior fast so pipes never stall into timeouts","Log at info/debug level to keep this out of alerting"],"tags":["trojan","fallback","relay"],"backgroundTag":null,"analyzedSha":"7d214f8b094f75322fa3990f8aadad1c912f24f5","analyzedAt":"2026-08-15T14:26:24.325Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}