grpc/grpc-go · critical
slice bounds out of range [%d:%d] with length 0
Error message
slice bounds out of range [%d:%d] with length 0
What it means
emptyBuffer (mem/buffers.go:260) is the zero-length Buffer returned by buffer.Slice when the requested range is empty (line 194-196). emptyBuffer.Slice (line 273-278) only permits Slice(0,0); any other indices panic with this custom out-of-range message because the buffer's length is 0. This mirrors Go's native slice-bounds panic but with an explicit, actionable message.
Source
Thrown at mem/buffers.go:275
return buf.split(n)
}
type emptyBuffer struct{}
func (e emptyBuffer) ReadOnlyData() []byte {
return nil
}
func (e emptyBuffer) Ref() {}
func (e emptyBuffer) Free() {}
func (e emptyBuffer) Len() int {
return 0
}
func (e emptyBuffer) Slice(start, end int) Buffer {
if start != 0 || end != 0 {
panic(fmt.Sprintf("slice bounds out of range [%d:%d] with length 0", start, end))
}
return e
}
func (e emptyBuffer) split(int) (left, right Buffer) {
return e, e
}
func (e emptyBuffer) read([]byte) (int, Buffer) {
return 0, e
}
// SliceBuffer is a Buffer implementation that wraps a byte slice. It provides
// methods for reading, splitting, and managing the byte slice.
type SliceBuffer []byte
// ReadOnlyData returns the byte slice.
func (s SliceBuffer) ReadOnlyData() []byte { return s }View on GitHub (pinned to 0c51461d27)
Solutions
- Check Len() (or bounds) before slicing: only call Slice when start <= end <= Len().
- Handle the empty case explicitly (skip or return the empty buffer) rather than slicing blindly.
- Validate indices against the current buffer length, not a cached/stale length.
Example fix
// before
sub := buf.Slice(0, frameLen) // if buf is empty and frameLen>0 -> panic
// after
if buf.Len() == 0 {
return buf // nothing to slice
}
sub := buf.Slice(0, min(frameLen, buf.Len())) Defensive patterns
Strategy: validation
Validate before calling
// Bounds-check before slicing any buffer, especially empty ones.
func safeSliceAny(b mem.Buffer, start, end int) mem.Buffer {
if end < start || start < 0 || end > b.Len() {
return nil // or return b unchanged
}
return b.Slice(start, end)
} Prevention
- Check Len() before slicing; only Slice when 0 <= start <= end <= Len().
- Handle the empty-buffer case explicitly instead of slicing blindly.
- Validate against current Len(), not a cached length.
When it happens
Trigger: Obtaining an empty Buffer (Len()==0, e.g. from slicing a zero-length range or from Copy of empty data) and then calling Slice(start, end) where start != 0 or end != 0; computing slice indices without checking the buffer length first.
Common situations: Generic buffer-slicing code that assumes non-zero length; codecs that pre-slice fixed-size frames and hit a zero-length frame; tests that pass empty data through slicing helpers.
Related errors
- Cannot read freed buffer
- Cannot ref freed buffer
- Cannot free freed buffer
- Cannot slice freed buffer
- Cannot split freed buffer
AI-assisted analysis of grpc/grpc-go@0c51461d27 (2026-08-11).
Data as JSON: /api/errors/a8a85a28af513fde.
Report an issue: GitHub.