VictoriaMetrics/VictoriaMetrics · error
cannot read uint64: %w
Error message
cannot read uint64: %w
What it means
Returned by vmselectRequestCtx.readUint64 when io.ReadFull cannot read the full 8 bytes of a uint64 field from the vmselect connection and the error is not a clean EOF. The underlying io error is wrapped with %w. Like the uint32 variant, it signals a truncated or broken binary protocol stream (readTimeRange, processRegisterMetricNames callers).
Source
Thrown at lib/vmselectapi/server.go:339
func (ctx *vmselectRequestCtx) readUint32() (uint32, error) {
ctx.sizeBuf = bytesutil.ResizeNoCopyMayOverallocate(ctx.sizeBuf, 4)
if _, err := io.ReadFull(ctx.bc, ctx.sizeBuf); err != nil {
if err == io.EOF {
return 0, err
}
return 0, fmt.Errorf("cannot read uint32: %w", err)
}
n := encoding.UnmarshalUint32(ctx.sizeBuf)
return n, nil
}
func (ctx *vmselectRequestCtx) readUint64() (uint64, error) {
ctx.sizeBuf = bytesutil.ResizeNoCopyMayOverallocate(ctx.sizeBuf, 8)
if _, err := io.ReadFull(ctx.bc, ctx.sizeBuf); err != nil {
if err == io.EOF {
return 0, err
}
return 0, fmt.Errorf("cannot read uint64: %w", err)
}
n := encoding.UnmarshalUint64(ctx.sizeBuf)
return n, nil
}
func (ctx *vmselectRequestCtx) readInt64() (int64, error) {
ctx.sizeBuf = bytesutil.ResizeNoCopyMayOverallocate(ctx.sizeBuf, 8)
if _, err := io.ReadFull(ctx.bc, ctx.sizeBuf); err != nil {
if err == io.EOF {
return 0, err
}
return 0, fmt.Errorf("cannot read int64: %w", err)
}
n := encoding.UnmarshalInt64(ctx.sizeBuf)
return n, nil
}
func (ctx *vmselectRequestCtx) readAccountIDProjectID() (uint32, uint32, error) {View on GitHub (pinned to 5079fb58f1)
Solutions
- Confirm the client writes uint64 fields as exactly 8 bytes little-endian.
- Inspect the wrapped error: unexpected-EOF implies truncated write; reset implies dropped connection.
- Align VictoriaMetrics component versions (vmagent/vminsert vs vmselect).
- Check idle/read timeouts on load balancers between cluster components.
- Retry on a new connection.
Example fix
// before (4-byte timestamp) binary.LittleEndian.PutUint32(buf, uint32(ts)) // after b := make([]byte, 8) binary.LittleEndian.PutUint64(b, uint64(ts)) conn.Write(b)
Defensive patterns
Strategy: try-catch
Validate before calling
// client side var v uint64 binary.LittleEndian.PutUint64(buf, v) // exactly 8 bytes, never manual append
Type guard
func isTruncatedRead(err error) bool { return errors.Is(err, io.ErrUnexpectedEOF) } Try / catch
v, err := readUint64(conn)
if err != nil {
if errors.Is(err, io.EOF) { return io.EOF }
return fmt.Errorf("failed reading uint64 field: %w", err)
} Prevention
- Use encoding.PutUint64 for all 64-bit fields
- Keep client and vmselect versions in lockstep
- Monitor connection-reset metrics between cluster nodes
- Avoid half-closing connections before the response is read
- Test protocol clients against a real vmselect instance
When it happens
Trigger: A caller sends fewer than 8 bytes for a time-range / timestamp field read by readTimeRange or processRegisterMetricNames; the connection is reset or times out while reading the 8-byte value.
Common situations: Custom clients writing timestamps as 4 bytes instead of 8; half-closed connections where the peer finished early; proxy buffering limits truncating the request; version-skewed cluster nodes.
Related errors
- cannot read uint32: %w
- cannot read int64: %w
- cannot read data size: %w
- cannot flush %q to server: %w
- cannot read message with size %d: %w; read only %d bytes
AI-assisted analysis of VictoriaMetrics/VictoriaMetrics@5079fb58f1 (2026-09-03).
Data as JSON: /api/errors/d5172d3fe2e78372.
Report an issue: GitHub.