XTLS/Xray-core · error
failed to write request
Error message
failed to write request
What it means
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.
Source
Thrown at proxy/shadowsocks/client.go:123
ctx, cancel := context.WithCancel(ctx)
timer := signal.CancelAfterInactivity(ctx, func() {
cancel()
if newCancel != nil {
newCancel()
}
}, sessionPolicy.Timeouts.ConnectionIdle)
if newCtx != nil {
ctx = newCtx
}
if request.Command == protocol.RequestCommandTCP {
requestDone := func() error {
defer timer.SetTimeout(sessionPolicy.Timeouts.DownlinkOnly)
bufferedWriter := buf.NewBufferedWriter(buf.NewWriter(conn))
bodyWriter, err := WriteTCPRequest(request, bufferedWriter)
if err != nil {
return errors.New("failed to write request").Base(err)
}
if err = buf.CopyOnceTimeout(link.Reader, bodyWriter, time.Millisecond*100); err != nil && err != buf.ErrNotTimeoutReader && err != buf.ErrReadTimeout {
return errors.New("failed to write A request payload").Base(err).AtWarning()
}
if err := bufferedWriter.SetBuffered(false); err != nil {
return err
}
return buf.Copy(link.Reader, bodyWriter, buf.UpdateActivity(timer))
}
responseDone := func() error {
defer timer.SetTimeout(sessionPolicy.Timeouts.UplinkOnly)
responseReader, err := ReadTCPResponse(user, conn)
if err != nil {View on GitHub (pinned to 7d214f8b09)
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.
Example fix
// before
"outbounds": [{
"protocol": "shadowsocks",
"settings": { "servers": [{ "address": "ss.example.com", "port": 443, "method": "aes-256-gcm", "password": "wrong-or-right" }] }
}]
// after: confirm server listens on the same port/method, e.g. on the server
// ss -lntp | grep 443 and check the server's own xray log for the reset Defensive patterns
Strategy: retry
Try / catch
if err := outbound.Dispatch(ctx, link); err != nil {
if errors.Is(err, io.EOF) || strings.Contains(err.Error(), "failed to write request") {
// transient transport failure: re-dial once with backoff
return retryOnce(ctx, outbound, link)
}
return err
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- failed to write A request payload
- connection ends
- cannot dial remote address
- Shadowsocks settings: "servers" should have one and only one
- failed to transport all UDP request
AI-assisted analysis of XTLS/Xray-core@7d214f8b09 (2026-08-15).
Data as JSON: /api/errors/61f8fb67e3037dcc.
Report an issue: GitHub.