XTLS/Xray-core · warning

failed to write A request payload

Error message

failed to write A request payload

What it means

Thrown during the trojan client's header-priming step: it attempts to copy one batch of request payload (with a 100ms timeout) into the trojan connection right after writing the header, so that the trojan server sees request bytes together with the header (mitigating replay fingerprinting). Only genuine copy errors (not the expected timeout/no-timeout-reader sentinel errors) produce this warning.

Source

Thrown at proxy/trojan/client.go:119

		bufferWriter := buf.NewBufferedWriter(buf.NewWriter(conn))

		connWriter := &ConnWriter{
			Writer:  bufferWriter,
			Target:  destination,
			Account: account,
		}

		var bodyWriter buf.Writer
		if destination.Network == net.Network_UDP {
			bodyWriter = &PacketWriter{Writer: connWriter, Target: destination}
		} else {
			bodyWriter = connWriter
		}

		// write some request payload to buffer
		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()
		}

		// Flush; bufferWriter.WriteMultiBuffer now is bufferWriter.writer.WriteMultiBuffer
		if err = bufferWriter.SetBuffered(false); err != nil {
			return errors.New("failed to flush payload").Base(err).AtWarning()
		}

		// Send header if not sent yet
		if _, err = connWriter.Write([]byte{}); err != nil {
			return err.(*errors.Error).AtWarning()
		}

		if err = buf.Copy(link.Reader, bodyWriter, buf.UpdateActivity(timer)); err != nil {
			return errors.New("failed to transfer request payload").Base(err).AtInfo()
		}

		return nil
	}

View on GitHub (pinned to 7d214f8b09)

Solutions

  1. Check the Base error and the trojan server logs at the same timestamp — an immediate server-side close usually means password mismatch.
  2. Verify the trojan password matches exactly on both ends.
  3. If the error is a TLS/write failure, inspect streamSettings (ALPN, serverName) on the client.
  4. Retry once: transient resets during prime-write are occasionally caused by server restarts.
Defensive patterns

Strategy: try-catch

Try / catch

if err := client.Process(ctx, link, dialer); err != nil {
	if strings.Contains(err.Error(), "failed to write A request payload") {
		// check base error: immediate server RST usually means password mismatch
	}
}

Prevention

When it happens

Trigger: buf.CopyOnceTimeout(link.Reader, bodyWriter, 100ms) returns an error that is neither buf.ErrNotTimeoutReader nor buf.ErrReadTimeout — e.g. the downstream connection writer fails (connection reset by the trojan server mid-handshake) or the inbound reader errors out.

Common situations: Trojan server closing the connection immediately after connect (wrong password → server drops after reading hash); upstream connection reset during early payload; outbound connWriter TLS error surfacing here.

Related errors


AI-assisted analysis of XTLS/Xray-core@7d214f8b09 (2026-08-15). Data as JSON: /api/errors/952ea9336ac5e63c. Report an issue: GitHub.