XTLS/Xray-core · error
read bytes: %w
Error message
read bytes: %w
What it means
Bytes.readFrom first reads a Varint length prefix; this message wraps a failure of that Varint read (itself usually 'read varint: %w'). It means the connection failed or ended while the length prefix of a byte-array field was being read — the payload was never reached.
Source
Thrown at transport/internet/finalmask/xmc/protocol.go:316
}
return nil
}
func (v *UUID) writeTo(w io.Writer) error {
_, err := w.Write(v[:])
if err != nil {
return fmt.Errorf("write UUID: %w", err)
}
return nil
}
type Bytes []byte
func (v *Bytes) readFrom(r io.Reader) error {
var length Varint
err := length.readFrom(r)
if err != nil {
return fmt.Errorf("read bytes: %w", err)
}
if length < 0 || length >= 1024 {
return fmt.Errorf("read bytes: invalid size: %d", length)
}
buf := make([]byte, length)
_, err = io.ReadFull(r, buf)
if err != nil {
return fmt.Errorf("read bytes: %w", err)
}
*v = append([]byte(*v), buf...)
return nil
}
View on GitHub (pinned to 7d214f8b09)
Solutions
- Treat io.EOF / io.ErrUnexpectedEOF on this path as 'peer ended the stream', and RST as abrupt close — log and reconnect.
- Confirm both endpoints run compatible padding presets; desync makes later reads fail here.
- Set read deadlines so dead peers fail fast instead of hanging before this error.
- Reproduce with verbose logging of packet IDs to find which field read failed.
Defensive patterns
Strategy: try-catch
Try / catch
if err := bytesField.readFrom(r); err != nil {
if errors.Is(err, io.EOF) || errors.Is(err, io.ErrUnexpectedEOF) {
return fmt.Errorf("peer closed during length prefix: %w", err)
}
return err // classify timeouts/resets separately
} Prevention
- Keep both endpoints on matching protocol versions and padding presets to avoid desync-driven EOFs.
- Set read deadlines per packet.
- Log the packet ID/field being read when failures cluster.
When it happens
Trigger: Peer closes or resets the connection between a packet header and a Bytes field; a read deadline expires mid-varint; the stream is desynchronized so the reader is at EOF where a varint should start.
Common situations: Server drops the client during login (bad profile, rate limit); half-open connections after network changes; framing desync caused by mismatched padding schedules making the reader consume the wrong bytes.
Related errors
- write boolean: %w
- write UUID: %w
- read remaining bytes: %w
- write remaining bytes: %w
- write bytes length: %w
AI-assisted analysis of XTLS/Xray-core@7d214f8b09 (2026-08-15).
Data as JSON: /api/errors/de43385ef792e753.
Report an issue: GitHub.