{"record":{"id":"2460eddbe432b439","repo":"thanos-io/thanos","slug":"fast-forward-range-reader","errorCode":null,"errorMessage":"fast forward range reader","messagePattern":"fast forward range reader","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/store/bucket.go","lineNumber":3767,"sourceCode":"\t\tdiff     uint32\n\t\tchunkLen int\n\t\tn        int\n\t)\n\n\tbufPooled, err := r.block.chunkPool.Get(r.block.estimatedMaxChunkSize)\n\tif err == nil {\n\t\tbuf = *bufPooled\n\t\tdefer r.block.chunkPool.Put(&buf)\n\t} else {\n\t\tbuf = make([]byte, r.block.estimatedMaxChunkSize)\n\t}\n\n\tfor i, pIdx := range pIdxs {\n\t\t// Fast forward range reader to the next chunk start in case of sparse (for our purposes) byte range.\n\t\tfor readOffset < int(pIdx.offset) {\n\t\t\twritten, err = bufReader.Discard(int(pIdx.offset) - int(readOffset))\n\t\t\tif err != nil {\n\t\t\t\treturn errors.Wrap(err, \"fast forward range reader\")\n\t\t\t}\n\t\t\treadOffset += written\n\t\t}\n\t\t// Presume chunk length to be reasonably large for common use cases.\n\t\t// However, declaration for EstimatedMaxChunkSize warns us some chunks could be larger in some rare cases.\n\t\t// This is handled further down below.\n\t\tchunkLen = r.block.estimatedMaxChunkSize\n\t\tif i+1 < len(pIdxs) {\n\t\t\tif diff = pIdxs[i+1].offset - pIdx.offset; int(diff) < chunkLen {\n\t\t\t\tchunkLen = int(diff)\n\t\t\t}\n\t\t}\n\t\tcb := buf[:chunkLen]\n\t\tn, err = io.ReadFull(bufReader, cb)\n\t\treadOffset += n\n\t\t// Unexpected EOF for last chunk could be a valid case. Any other errors are definitely real.\n\t\tif err != nil && !errors.Is(err, io.ErrUnexpectedEOF) && i != len(pIdxs)-1 {\n\t\t\treturn errors.Wrapf(err, \"read range for seq %d offset %x\", seq, pIdx.offset)","sourceCodeStart":3749,"sourceCodeEnd":3785,"githubUrl":"https://github.com/thanos-io/thanos/blob/35b8b991177def87ed52dcf10f9b6d87f07282c8/pkg/store/bucket.go#L3749-L3785","documentation":"Raised in bucketChunkReader.load while reading pre-fetched byte ranges from object storage: bufio.Reader.Discard fails when fast-forwarding the range reader to the next chunk's offset. The cause is an underlying read error on the object storage stream (connection reset, unexpected EOF), not a logic error in offsets.","triggerScenarios":"Thrown at pkg/store/bucket.go:3767 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Retry the query; transient object storage read errors often resolve","Check object store connectivity and range-request support","Reduce requested time range/chunk count if the streaming read keeps failing"],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"35b8b991177def87ed52dcf10f9b6d87f07282c8","analyzedAt":"2026-09-07T01:49:59.689Z","contentChangedAt":"2026-09-07T01:49:59.689Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}