VictoriaMetrics/VictoriaMetrics · error

cannot read isCompressed flag: %w

Error message

cannot read isCompressed flag: %w

What it means

In genericServer, after writing the first successResponse the server reads the client's isCompressed flag with readIsCompressed(c). This error wraps whatever I/O error that read returned. It means the server could not read the single-byte compression flag from the client before the handshake deadline expired or the connection dropped.

Source

Thrown at lib/handshake/handshake.go:216

	}

	return false
}

func genericServer(c net.Conn, compressionLevel int, readHelloMessage func(c net.Conn) error) (*BufferedConn, error) {
	if err := c.SetDeadline(time.Now().Add(*rpcHandshakeTimeout)); err != nil {
		return nil, fmt.Errorf("cannot set deadline: %w", err)
	}

	if err := readHelloMessage(c); err != nil {
		return nil, fmt.Errorf("cannot read hello message : %w", err)
	}
	if err := writeMessage(c, successResponse); err != nil {
		return nil, fmt.Errorf("cannot write success response on isCompressed: %w", err)
	}
	isRemoteCompressed, err := readIsCompressed(c)
	if err != nil {
		return nil, fmt.Errorf("cannot read isCompressed flag: %w", err)
	}
	if err := writeMessage(c, successResponse); err != nil {
		return nil, fmt.Errorf("cannot write success response on isCompressed: %w", err)
	}
	if err := writeIsCompressed(c, compressionLevel > 0); err != nil {
		return nil, fmt.Errorf("cannot write isCompressed flag: %w", err)
	}
	if err := readMessage(c, successResponse); err != nil {
		return nil, fmt.Errorf("cannot read success response on isCompressed: %w", err)
	}

	if err := c.SetDeadline(time.Time{}); err != nil {
		return nil, fmt.Errorf("cannot reset deadline: %w", err)
	}

	bc := newBufferedConn(c, compressionLevel, isRemoteCompressed)
	return bc, nil
}

View on GitHub (pinned to 5079fb58f1)

Solutions

  1. Check the wrapped error: io.EOF/ErrUnexpectedEOF usually means the peer closed or is not speaking the expected protocol — verify the client is a compatible VictoriaMetrics version.
  2. Raise -rpc.handshakeTimeout if the wrapped error is a timeout on high-latency links.
  3. Confirm nothing between the peers (LB, service mesh, firewall) truncates or times out short-lived connections during handshake.
  4. Filter these with handshake.IsClientNetworkError(err) so probes/scanners that hit the port do not pollute error logs.

Example fix

// before
bc, err := handshake.VMSelectServer(conn, compressionLevel)
if err != nil {
    return fmt.Errorf("handshake: %w", err)
}
// after: distinguish dead/mismatched peers from timeouts
bc, err := handshake.VMSelectServer(conn, compressionLevel)
if err != nil {
    if handshake.IsClientNetworkError(err) {
        return nil // peer vanished mid-handshake; nothing to do server-side
    }
    return fmt.Errorf("handshake: %w", err)
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Client side: ensure you only dial the VictoriaMetrics RPC port and send the hello promptly
conn.SetDeadline(time.Now().Add(handshakeTimeout))
if _, err := handshake.VMInsertClient(conn, helloMsg, compressionLevel); err != nil {
    return fmt.Errorf("peer does not speak the expected protocol: %w", err)
}

Type guard

func isCompressedFlagReadError(err error) bool {
    return err != nil && strings.Contains(err.Error(), "cannot read isCompressed flag")
}

Try / catch

bc, err := handshake.VMSelectServer(conn, compressionLevel)
if err != nil {
    switch {
    case errors.Is(err, io.EOF), errors.Is(err, io.ErrUnexpectedEOF):
        return nil // peer closed early: probe, crash, or version mismatch
    case handshake.IsTimeoutNetworkError(err):
        return fmt.Errorf("handshake timeout, raise -rpc.handshakeTimeout: %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: VMInsertServer/VMInsertServerWithLegacyHello/VMSelectServer accepted a connection and got past the hello exchange, but readIsCompressed(c) fails: the client closed the connection, sent a partial/short message (io.ErrUnexpectedEOF), or the rpcHandshakeTimeout deadline expired while waiting for the flag.

Common situations: Peer is not a VictoriaMetrics client and sends garbage or nothing after hello (wrong port, port scanner, monitoring probe); abrupt client termination; network partitions; handshake timeout too low for slow links; protocol/version mismatch where an older client never sends the isCompressed flag.

Related errors


AI-assisted analysis of VictoriaMetrics/VictoriaMetrics@5079fb58f1 (2026-09-03). Data as JSON: /api/errors/288b34a84a7af27b. Report an issue: GitHub.