XTLS/Xray-core · error
read remaining bytes: %w
Error message
read remaining bytes: %w
What it means
RestBytes.readFrom slurps everything remaining on the stream with io.ReadAll and wraps any failure with this message. RestBytes is the trailing 'rest of packet' field, so this error means the connection failed while draining the remainder of a frame — typically the peer disconnecting mid-read or a read deadline firing.
Source
Thrown at transport/internet/finalmask/xmc/protocol.go:340
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
}
type RestBytes []byte
func (v *RestBytes) readFrom(r io.Reader) error {
buf, err := io.ReadAll(r)
if err != nil {
return fmt.Errorf("read remaining bytes: %w", err)
}
*v = append((*v)[:0], buf...)
return nil
}
func (v *RestBytes) writeTo(w io.Writer) error {
if _, err := w.Write(*v); err != nil {
return fmt.Errorf("write remaining bytes: %w", err)
}
return nil
}
func (v *Bytes) writeTo(w io.Writer) error {
length := Varint(len(*v))
err := length.writeTo(w)
if err != nil {
return fmt.Errorf("write bytes length: %w", err)
}View on GitHub (pinned to 7d214f8b09)
Solutions
- Distinguish clean EOF (peer closed gracefully — often normal at end of session) from ErrUnexpectedEOF/reset (failure).
- Set read deadlines and refresh them per packet to avoid indefinite blocking then abrupt timeout errors.
- Reconnect/retry at the session layer if the protocol supports resumption.
- Log the packet ID being parsed when the error occurs to identify the phase.
Defensive patterns
Strategy: try-catch
Try / catch
if err := rest.readFrom(r); err != nil {
if errors.Is(err, io.EOF) {
return nil // graceful close at boundary during drain is normal
}
return fmt.Errorf("failed draining packet tail: %w", err)
} Prevention
- Refresh read deadlines after each packet to survive NAT idle timeouts.
- Distinguish graceful EOF from truncation before alerting.
- Log the packet being parsed when the drain fails.
When it happens
Trigger: Reading a packet whose last field is RestBytes when the connection resets or EOFs before the reader finishes; ReadAll hitting a deadlines error on a Conn.
Common situations: Server closes the connection right after sending a partial final packet; long-lived connection killed by NAT idle timeout while a large trailing field was in flight.
Related errors
AI-assisted analysis of XTLS/Xray-core@7d214f8b09 (2026-08-15).
Data as JSON: /api/errors/e08ba68de356a08d.
Report an issue: GitHub.