XTLS/Xray-core · error
failed to read from connection
Error message
failed to read from connection
What it means
Thrown by the SOCKS inbound when reading the first byte of a TCP connection fails with something other than a clean immediate EOF. The first byte determines whether the connection is SOCKS5 (0x05), SOCKS4/4a (0x04), or should be re-parsed as HTTP. A zero-byte read with a non-EOF error (reset, timeout, TLS garbage) lands here.
Source
Thrown at proxy/socks/server.go:85
inbound := session.InboundFromContext(ctx)
inbound.Name = "socks"
inbound.CanSpliceCopy = 2
inbound.User = &protocol.MemoryUser{
Level: s.config.UserLevel,
}
if !proxy.IsRAWTransportWithoutSecurity(conn) {
inbound.CanSpliceCopy = 3
}
switch network {
case net.Network_TCP:
firstbyte := make([]byte, 1)
if n, err := conn.Read(firstbyte); n == 0 {
if goerrors.Is(err, io.EOF) {
errors.LogInfo(ctx, "Connection closed immediately, likely health check connection")
return nil
}
return errors.New("failed to read from connection").Base(err)
}
if firstbyte[0] != 5 && firstbyte[0] != 4 { // Check if it is Socks5/4/4a
errors.LogDebug(ctx, "Not Socks request, try to parse as HTTP request")
return s.httpServer.ProcessWithFirstbyte(ctx, network, conn, dispatcher, firstbyte...)
}
return s.processTCP(ctx, conn, dispatcher, firstbyte)
default:
return errors.New("unknown network: ", network)
}
}
func (s *Server) processTCP(ctx context.Context, conn stat.Connection, dispatcher routing.Dispatcher, firstbyte []byte) error {
plcy := s.policy()
if err := conn.SetReadDeadline(time.Now().Add(plcy.Timeouts.Handshake)); err != nil {
errors.LogInfoInner(ctx, err, "failed to set deadline")
}
inbound := session.InboundFromContext(ctx)View on GitHub (pinned to 7d214f8b09)
Solutions
- Check the Base error: connection reset by peer vs i/o timeout tells you scanner vs timeout.
- If TLS was intended, enable TLS on the inbound (streamSettings.security) so the TLS layer consumes those bytes first.
- For timeout causes, raise policy.timeouts.handshake on the inbound.
- Expose the inbound only on loopback/LAN or front it with a firewall if scanner noise is constant.
Defensive patterns
Strategy: try-catch
Try / catch
if err := inbound.Process(ctx, conn, dispatcher); err != nil {
if strings.Contains(err.Error(), "failed to read from connection") {
return nil // treat as scanner/noise; don't fail the listener
}
log.Warn(err)
} Prevention
- Front public inbounds with a firewall or fail2ban for scan noise.
- Match TLS settings on both ends to avoid protocol-byte collisions.
- Set sane handshake timeouts to shed dead peers quickly.
When it happens
Trigger: conn.Read on a 1-byte buffer returns n == 0 with a connection-reset, i/o-timeout, or protocol error instead of io.EOF. Typical for port scanners that open and RST, or TLS clients connecting to a plaintext SOCKS port.
Common situations: Internet-exposed inbound port probed by mass scanners; TLS client (e.g. someone configured tls on the client but not the server); NAT/firewall sending RST; handshake timeout from the inbound policy exceeded.
Related errors
- unknown network: {network}
- inbound gateway not specified
- failed to read request
- failed to dispatch request
- UDP associate with listen port failed
AI-assisted analysis of XTLS/Xray-core@7d214f8b09 (2026-08-15).
Data as JSON: /api/errors/e4bd20679fca1ea4.
Report an issue: GitHub.