{"record":{"id":"61f8fb67e3037dcc","repo":"XTLS/Xray-core","slug":"failed-to-write-request-61f8fb","errorCode":null,"errorMessage":"failed to write request","messagePattern":"failed to write request","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"proxy/shadowsocks/client.go","lineNumber":123,"sourceCode":"\tctx, cancel := context.WithCancel(ctx)\n\ttimer := signal.CancelAfterInactivity(ctx, func() {\n\t\tcancel()\n\t\tif newCancel != nil {\n\t\t\tnewCancel()\n\t\t}\n\t}, sessionPolicy.Timeouts.ConnectionIdle)\n\n\tif newCtx != nil {\n\t\tctx = newCtx\n\t}\n\n\tif request.Command == protocol.RequestCommandTCP {\n\t\trequestDone := func() error {\n\t\t\tdefer timer.SetTimeout(sessionPolicy.Timeouts.DownlinkOnly)\n\t\t\tbufferedWriter := buf.NewBufferedWriter(buf.NewWriter(conn))\n\t\t\tbodyWriter, err := WriteTCPRequest(request, bufferedWriter)\n\t\t\tif err != nil {\n\t\t\t\treturn errors.New(\"failed to write request\").Base(err)\n\t\t\t}\n\n\t\t\tif err = buf.CopyOnceTimeout(link.Reader, bodyWriter, time.Millisecond*100); err != nil && err != buf.ErrNotTimeoutReader && err != buf.ErrReadTimeout {\n\t\t\t\treturn errors.New(\"failed to write A request payload\").Base(err).AtWarning()\n\t\t\t}\n\n\t\t\tif err := bufferedWriter.SetBuffered(false); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\n\t\t\treturn buf.Copy(link.Reader, bodyWriter, buf.UpdateActivity(timer))\n\t\t}\n\n\t\tresponseDone := func() error {\n\t\t\tdefer timer.SetTimeout(sessionPolicy.Timeouts.UplinkOnly)\n\n\t\t\tresponseReader, err := ReadTCPResponse(user, conn)\n\t\t\tif err != nil {","sourceCodeStart":105,"sourceCodeEnd":141,"githubUrl":"https://github.com/XTLS/Xray-core/blob/7d214f8b094f75322fa3990f8aadad1c912f24f5/proxy/shadowsocks/client.go#L105-L141","documentation":"Thrown while establishing a Shadowsocks client TCP session: the outbound request header (target address, cipher/AEAD framing) could not be written to the remote Shadowsocks server connection via WriteTCPRequest. It wraps the underlying transport error, so the root cause is almost always a broken, reset, or timed-out socket rather than a protocol logic bug. The connection is aborted before any payload is relayed.","triggerScenarios":"Calling the Shadowsocks outbound handler for a TCP request where WriteTCPRequest fails: remote server refuses/resets the connection after accept, TLS/transport handshake fails mid-write, dialer-provided conn is already closed, or AEAD encoding of the address header returns an error.","commonSituations":"Shadowsocks server port reachable but process crashing on accept; firewall or middlebox killing the stream right after connect; outbound conn handed to the proxy already timed out by a short ConnectionIdle policy; server behind NAT with stale port-forward.","solutions":["Verify the remote Shadowsocks server is up and the address/port/password in the outbound config are correct.","Test raw reachability from the Xray host (e.g. curl telnet://host:port or nc) to rule out firewall/NAT reset.","Check server logs at the same timestamp — a reset on accept usually appears there; fix server-side crash or cipher mismatch.","Review policy timeouts (connIdle) so the conn is not reaped before the request header is written.","Capture with tcpdump to confirm whether the FIN/RST comes from the network path or the server."],"exampleFix":"// before\n\"outbounds\": [{\n  \"protocol\": \"shadowsocks\",\n  \"settings\": { \"servers\": [{ \"address\": \"ss.example.com\", \"port\": 443, \"method\": \"aes-256-gcm\", \"password\": \"wrong-or-right\" }] }\n}]\n// after: confirm server listens on the same port/method, e.g. on the server\n// ss -lntp | grep 443  and check the server's own xray log for the reset","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"if err := outbound.Dispatch(ctx, link); err != nil {\n  if errors.Is(err, io.EOF) || strings.Contains(err.Error(), \"failed to write request\") {\n    // transient transport failure: re-dial once with backoff\n    return retryOnce(ctx, outbound, link)\n  }\n  return err\n}","preventionTips":["Monitor server reachability with health checks before routing traffic to a Shadowsocks outbound.","Keep policy timeouts (connIdle) large enough for slow-starting servers.","Log the Base error chain to distinguish dial failures from header-write failures."],"tags":["shadowsocks","network","outbound","tcp","connection-reset"],"backgroundTag":null,"analyzedSha":"7d214f8b094f75322fa3990f8aadad1c912f24f5","analyzedAt":"2026-08-15T14:26:24.325Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}