XTLS/Xray-core · error
write packet data: %w
Error message
write packet data: %w
What it means
writePacketWithLength encodes all fields into a frame and then writes it atomically with writeFull; this error wraps that final write failing. It is the outermost write error for any outbound packet, so any underlying connection problem (closed, reset, deadline) shows up here after the frame was built successfully.
Source
Thrown at transport/internet/finalmask/xmc/protocol.go:389
if err != nil {
return 0, fmt.Errorf("read byte: %w", err)
}
return buf[0], nil
}
func writePacket(w io.Writer, packetID int, fields ...field) error {
_, err := writePacketWithLength(w, packetID, fields...)
return err
}
func writePacketWithLength(w io.Writer, packetID int, fields ...field) (int, error) {
frame, err := encodePacket(packetID, fields...)
if err != nil {
return 0, err
}
if err = writeFull(w, frame); err != nil {
return 0, fmt.Errorf("write packet data: %w", err)
}
return len(frame), nil
}
func encodePacket(packetID int, fields ...field) ([]byte, error) {
var dataBuf bytes.Buffer
for _, field := range fields {
err := field.writeTo(&dataBuf)
if err != nil {
return nil, fmt.Errorf("write packet field: %w", err)
}
}
if dataBuf.Len() > maxPacketDataLength {
return nil, fmt.Errorf("write packet: bad length: %d", dataBuf.Len())
}
packetIDVarint := Varint(packetID)View on GitHub (pinned to 7d214f8b09)
Solutions
- Once writePacketWithLength returns this error, treat the connection as dead — do not retry on the same conn.
- Classify the wrapped error (closed vs timeout vs reset) for metrics/alerting.
- Size write deadlines to your largest padded frame.
- Route sends through a single writer goroutine to avoid close/write races.
Defensive patterns
Strategy: try-catch
Try / catch
if _, err := writePacketWithLength(w, id, fields...); err != nil {
teardownConn()
var nerr net.Error
if errors.As(err, &nerr) && nerr.Timeout() {
return fmt.Errorf("frame flush timed out (deadline too small?): %w", err)
}
return fmt.Errorf("connection lost while sending packet %d: %w", id, err)
} Prevention
- Treat any writePacketWithLength failure as fatal for the connection; reconnect rather than retry on the same conn.
- Set write deadlines covering your largest padded frame.
- Export metrics split by closed/timeout/reset to monitor transport health.
When it happens
Trigger: writePacket on a connection the peer already closed; write deadline exceeded while flushing a large frame; conn closed locally by error handling while a packet send was queued.
Common situations: Sending keepalive/login packets right as the server drops the connection; slow links where big padded frames exceed deadlines; races between connection teardown and pending sends.
Related errors
AI-assisted analysis of XTLS/Xray-core@7d214f8b09 (2026-08-15).
Data as JSON: /api/errors/d4973c9234228f03.
Report an issue: GitHub.