{"record":{"id":"be189cae5161a650","repo":"XTLS/Xray-core","slug":"failed-to-transfer-request","errorCode":null,"errorMessage":"failed to transfer request","messagePattern":"failed to transfer request","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"proxy/trojan/server.go","lineNumber":340,"sourceCode":"\nfunc (s *Server) handleConnection(ctx context.Context, sessionPolicy policy.Session,\n\tdestination net.Destination,\n\tclientReader buf.Reader,\n\tclientWriter buf.Writer, dispatcher routing.Dispatcher,\n) error {\n\tctx, cancel := context.WithCancel(ctx)\n\ttimer := signal.CancelAfterInactivity(ctx, cancel, sessionPolicy.Timeouts.ConnectionIdle)\n\tctx = policy.ContextWithBufferPolicy(ctx, sessionPolicy.Buffer)\n\n\tlink, err := dispatcher.Dispatch(ctx, destination)\n\tif err != nil {\n\t\treturn errors.New(\"failed to dispatch request to \", destination).Base(err)\n\t}\n\n\trequestDone := func() error {\n\t\tdefer timer.SetTimeout(sessionPolicy.Timeouts.DownlinkOnly)\n\t\tif buf.Copy(clientReader, link.Writer, buf.UpdateActivity(timer)) != nil {\n\t\t\treturn errors.New(\"failed to transfer request\").Base(err)\n\t\t}\n\t\treturn nil\n\t}\n\n\tresponseDone := func() error {\n\t\tdefer timer.SetTimeout(sessionPolicy.Timeouts.UplinkOnly)\n\n\t\tif err := buf.Copy(link.Reader, clientWriter, buf.UpdateActivity(timer)); err != nil {\n\t\t\treturn errors.New(\"failed to write response\").Base(err)\n\t\t}\n\t\treturn nil\n\t}\n\n\trequestDonePost := task.OnSuccess(requestDone, task.Close(link.Writer))\n\tif err := task.Run(ctx, requestDonePost, responseDone); err != nil {\n\t\tcommon.Must(common.Interrupt(link.Reader))\n\t\tcommon.Must(common.Interrupt(link.Writer))\n\t\treturn errors.New(\"connection ends\").Base(err)","sourceCodeStart":322,"sourceCodeEnd":358,"githubUrl":"https://github.com/XTLS/Xray-core/blob/7d214f8b094f75322fa3990f8aadad1c912f24f5/proxy/trojan/server.go#L322-L358","documentation":"Copying the client's uplink bytes to the dispatched outbound link failed (buf.Copy from clientReader to link.Writer returned non-nil). This is the request-direction pipe of the trojan relay; it dies when the client connection breaks or the outbound writer errors.","triggerScenarios":"Client disconnects abruptly (RST) mid-transfer, outbound writer is closed by the other pipe finishing first, or an i/o timeout from policy Timeouts.ConnectionIdle fires via the inactivity timer.","commonSituations":"Normal connection teardown races (one side closes first), flaky client networks, or idle timeouts shorter than the workload's silence gaps.","solutions":["Check whether it co-occurs with [725]/[726] at session close — then it is normal teardown noise","If it fires mid-transfer, raise Timeouts.ConnectionIdle in the policy applied to the user's level","Inspect the Base error to distinguish client-side read failure from outbound write failure"],"exampleFix":"// json policy: give long-lived sessions more idle headroom\n\"policy\": {\"levels\": {\"0\": {\"handshake\": 4, \"connIdle\": 300}}, \"system\": {\"statsOutboundUplink\": true}}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"if err := buf.Copy(clientReader, link.Writer, buf.UpdateActivity(timer)); err != nil {\n    // pipe broke (client gone or outbound closed): end this direction only\n    return errors.New(\"failed to transfer request\").Base(err)\n}","preventionTips":["Set policy connIdle above your workload's longest silent gap","Let task.Run aggregate both pipes rather than handling mid-relay recovery manually","Treat paired request/response copy failures at close time as normal teardown"],"tags":["trojan","relay","copy"],"backgroundTag":null,"analyzedSha":"7d214f8b094f75322fa3990f8aadad1c912f24f5","analyzedAt":"2026-08-15T14:26:24.325Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}