XTLS/Xray-core · error
write minecraft keep-alive: %w
Error message
write minecraft keep-alive: %w
What it means
writeKeepAlive failed to write a 0x04 keep-alive reply (client side, triggered from Read) or periodic keep-alive (server side). The wrapped writePacket error means the underlying connection write failed — broken pipe, closed conn, or write deadline exceeded.
Source
Thrown at transport/internet/finalmask/xmc/packet_stream.go:165
var channel String
if err := channel.readFrom(r); err != nil {
return nil, false, fmt.Errorf("read minecraft custom payload channel: %w", err)
}
if string(channel) != packetChannel {
return nil, false, nil
}
payload := make([]byte, r.Len())
if _, err := io.ReadFull(r, payload); err != nil {
return nil, false, fmt.Errorf("read minecraft custom payload data: %w", err)
}
return payload, true, nil
}
func (s *packetStream) writeKeepAlive(id Long) error {
s.writeMu.Lock()
defer s.writeMu.Unlock()
if err := writePacket(s.writer, configurationKeepAlive, &id); err != nil {
return fmt.Errorf("write minecraft keep-alive: %w", err)
}
return nil
}
func (s *packetStream) keepAliveLoop() {
ticker := time.NewTicker(keepAlivePeriod)
defer ticker.Stop()
for {
select {
case <-ticker.C:
id := Long(s.keepAliveID.Add(1))
if err := s.writeKeepAlive(id); err != nil {
return
}
case <-s.done:
return
}
}View on GitHub (pinned to 7d214f8b09)
Solutions
- Inspect the wrapped error (EPIPE, ECONNRESET, os.ErrDeadlineExceeded) for the true cause
- Mark the connection dead and tear it down; keep-alive failure is fatal by design
- Ensure network path allows bidirectional traffic and keep-alive interval (15s) is shorter than NAT idle timeouts
- Reconnect at the application layer
Defensive patterns
Strategy: try-catch
Try / catch
if err := stream.Write(payload); err != nil {
if strings.Contains(err.Error(), "write minecraft keep-alive") {
conn.Close() // keep-alive path is dead, connection must be rebuilt
}
return err
} Prevention
- Keep the 15s keep-alive interval below NAT/firewall idle timeouts
- Close streams deterministically with Stop() when tearing down
- Treat any keep-alive write failure as connection-fatal
When it happens
Trigger: Client receives a server keep-alive but the connection has since died; server's 15-second keepAliveLoop ticker fires after the peer vanished; write deadline set during handshake is still active.
Common situations: Peer abruptly disappears (crash, NAT timeout); asymmetric connectivity loss where reads still succeed but writes fail; long-running tunnels through aggressive firewalls.
Related errors
- write minecraft custom payload: %w
- read minecraft packet stream: %w
- read minecraft keep-alive: %w
- LRU size is bigger than subnet size
- outbound failed to relay connection
AI-assisted analysis of XTLS/Xray-core@7d214f8b09 (2026-08-15).
Data as JSON: /api/errors/6b65012280e4a308.
Report an issue: GitHub.