XTLS/Xray-core · error

read byte: %w

Error message

read byte: %w

What it means

readByte performs io.ReadFull for a single byte and wraps failures. Because it reads only 1 byte, io.EOF here means the peer closed the stream exactly at a packet boundary (clean close), while io.ErrUnexpectedEOF/reset means truncation or abrupt disconnect. Most protocol field reads bottom out in this function.

Source

Thrown at transport/internet/finalmask/xmc/protocol.go:372

	length := Varint(len(*v))
	err := length.writeTo(w)
	if err != nil {
		return fmt.Errorf("write bytes length: %w", err)
	}

	_, err = w.Write(*v)
	if err != nil {
		return fmt.Errorf("write bytes: %w", err)
	}

	return nil
}

func readByte(r io.Reader) (byte, error) {
	var buf [1]byte
	_, err := io.ReadFull(r, buf[:])
	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)
	}

View on GitHub (pinned to 7d214f8b09)

Solutions

  1. Special-case io.EOF: if it arrives at a packet boundary it is a graceful close — exit cleanly instead of logging an error.
  2. For resets/truncation, reconnect with backoff at the session layer.
  3. Keep TCP keepalives enabled so dead peers are detected.
  4. Correlate with server-side logs to see who closed first.

Example fix

// before
if err := field.readFrom(r); err != nil { log.Error(err) }
// after
if err := field.readFrom(r); err != nil {
    if errors.Is(err, io.EOF) { return nil }
    return err
}
Defensive patterns

Strategy: try-catch

Try / catch

b, err := readByte(r)
if err != nil {
    if errors.Is(err, io.EOF) {
        return io.EOF // clean close at packet boundary: exit normally
    }
    if errors.Is(err, io.ErrUnexpectedEOF) {
        return fmt.Errorf("peer truncated mid-field: %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: Any field-level read on a closed or truncated connection: peer disconnect between packets, RST from firewall, read deadline expiry at a field start.

Common situations: Normal session end surfacing as this error during shutdown; server kicking the client (bad credentials, duplicate login); idle NAT timeout killing the connection.

Related errors


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