{"record":{"id":"952ea9336ac5e63c","repo":"XTLS/Xray-core","slug":"failed-to-write-a-request-payload-952ea9","errorCode":null,"errorMessage":"failed to write A request payload","messagePattern":"failed to write A request payload","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"proxy/trojan/client.go","lineNumber":119,"sourceCode":"\n\t\tbufferWriter := buf.NewBufferedWriter(buf.NewWriter(conn))\n\n\t\tconnWriter := &ConnWriter{\n\t\t\tWriter:  bufferWriter,\n\t\t\tTarget:  destination,\n\t\t\tAccount: account,\n\t\t}\n\n\t\tvar bodyWriter buf.Writer\n\t\tif destination.Network == net.Network_UDP {\n\t\t\tbodyWriter = &PacketWriter{Writer: connWriter, Target: destination}\n\t\t} else {\n\t\t\tbodyWriter = connWriter\n\t\t}\n\n\t\t// write some request payload to buffer\n\t\tif err = buf.CopyOnceTimeout(link.Reader, bodyWriter, time.Millisecond*100); err != nil && err != buf.ErrNotTimeoutReader && err != buf.ErrReadTimeout {\n\t\t\treturn errors.New(\"failed to write A request payload\").Base(err).AtWarning()\n\t\t}\n\n\t\t// Flush; bufferWriter.WriteMultiBuffer now is bufferWriter.writer.WriteMultiBuffer\n\t\tif err = bufferWriter.SetBuffered(false); err != nil {\n\t\t\treturn errors.New(\"failed to flush payload\").Base(err).AtWarning()\n\t\t}\n\n\t\t// Send header if not sent yet\n\t\tif _, err = connWriter.Write([]byte{}); err != nil {\n\t\t\treturn err.(*errors.Error).AtWarning()\n\t\t}\n\n\t\tif err = buf.Copy(link.Reader, bodyWriter, buf.UpdateActivity(timer)); err != nil {\n\t\t\treturn errors.New(\"failed to transfer request payload\").Base(err).AtInfo()\n\t\t}\n\n\t\treturn nil\n\t}","sourceCodeStart":101,"sourceCodeEnd":137,"githubUrl":"https://github.com/XTLS/Xray-core/blob/7d214f8b094f75322fa3990f8aadad1c912f24f5/proxy/trojan/client.go#L101-L137","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Check the Base error and the trojan server logs at the same timestamp — an immediate server-side close usually means password mismatch.","Verify the trojan password matches exactly on both ends.","If the error is a TLS/write failure, inspect streamSettings (ALPN, serverName) on the client.","Retry once: transient resets during prime-write are occasionally caused by server restarts."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"if err := client.Process(ctx, link, dialer); err != nil {\n\tif strings.Contains(err.Error(), \"failed to write A request payload\") {\n\t\t// check base error: immediate server RST usually means password mismatch\n\t}\n}","preventionTips":["Confirm passwords match on both ends before debugging deeper.","Watch trojan server logs for early-close events at the same timestamps.","Treat transient resets at this stage as retryable once."],"tags":["trojan","outbound","payload","write-error","handshake"],"backgroundTag":null,"analyzedSha":"7d214f8b094f75322fa3990f8aadad1c912f24f5","analyzedAt":"2026-08-15T14:26:24.325Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}