{"record":{"id":"a8a85a28af513fde","repo":"grpc/grpc-go","slug":"slice-bounds-out-of-range-d-d-with-length-0","errorCode":null,"errorMessage":"slice bounds out of range [%d:%d] with length 0","messagePattern":"slice bounds out of range \\[(.+?):(.+?)\\] with length 0","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"mem/buffers.go","lineNumber":275,"sourceCode":"\treturn buf.split(n)\n}\n\ntype emptyBuffer struct{}\n\nfunc (e emptyBuffer) ReadOnlyData() []byte {\n\treturn nil\n}\n\nfunc (e emptyBuffer) Ref()  {}\nfunc (e emptyBuffer) Free() {}\n\nfunc (e emptyBuffer) Len() int {\n\treturn 0\n}\n\nfunc (e emptyBuffer) Slice(start, end int) Buffer {\n\tif start != 0 || end != 0 {\n\t\tpanic(fmt.Sprintf(\"slice bounds out of range [%d:%d] with length 0\", start, end))\n\t}\n\treturn e\n}\n\nfunc (e emptyBuffer) split(int) (left, right Buffer) {\n\treturn e, e\n}\n\nfunc (e emptyBuffer) read([]byte) (int, Buffer) {\n\treturn 0, e\n}\n\n// SliceBuffer is a Buffer implementation that wraps a byte slice. It provides\n// methods for reading, splitting, and managing the byte slice.\ntype SliceBuffer []byte\n\n// ReadOnlyData returns the byte slice.\nfunc (s SliceBuffer) ReadOnlyData() []byte { return s }","sourceCodeStart":257,"sourceCodeEnd":293,"githubUrl":"https://github.com/grpc/grpc-go/blob/0c51461d27177d997e14c642fe18c11668fc09a3/mem/buffers.go#L257-L293","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nsub := buf.Slice(0, frameLen) // if buf is empty and frameLen>0 -> panic\n\n// after\nif buf.Len() == 0 {\n    return buf // nothing to slice\n}\nsub := buf.Slice(0, min(frameLen, buf.Len()))","handlingStrategy":"validation","validationCode":"// Bounds-check before slicing any buffer, especially empty ones.\nfunc safeSliceAny(b mem.Buffer, start, end int) mem.Buffer {\n    if end < start || start < 0 || end > b.Len() {\n        return nil // or return b unchanged\n    }\n    return b.Slice(start, end)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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."],"tags":["mem","buffer","bounds","panic","go"],"backgroundTag":null,"analyzedSha":"0c51461d27177d997e14c642fe18c11668fc09a3","analyzedAt":"2026-08-11T14:49:15.055Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}