{"record":{"id":"18d276f44bc4b91f","repo":"thanos-io/thanos","slug":"read-position-d","errorCode":null,"errorMessage":"read position: %d","messagePattern":"read position: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/store/cache/caching_bucket.go","lineNumber":536,"sourceCode":"\treturn &subrangesReader{\n\t\tsubrangeSize: subrangeSize,\n\t\toffsetsKeys:  offsetsKeys,\n\t\tsubranges:    subranges,\n\n\t\treadOffset: readOffset,\n\t\tremaining:  remaining,\n\t}\n}\n\nfunc (c *subrangesReader) Read(p []byte) (n int, err error) {\n\tif c.remaining <= 0 {\n\t\treturn 0, io.EOF\n\t}\n\n\tcurrentSubrangeOffset := (c.readOffset / c.subrangeSize) * c.subrangeSize\n\tcurrentSubrange, err := c.subrangeAt(currentSubrangeOffset)\n\tif err != nil {\n\t\treturn 0, errors.Wrapf(err, \"read position: %d\", c.readOffset)\n\t}\n\n\toffsetInSubrange := int(c.readOffset - currentSubrangeOffset)\n\ttoCopy := len(currentSubrange) - offsetInSubrange\n\tif toCopy <= 0 {\n\t\t// This can only happen if subrange's length is not subrangeSize, and reader is told to read more data.\n\t\treturn 0, errors.Errorf(\"no more data left in subrange at position %d, subrange length %d, reading position %d\", currentSubrangeOffset, len(currentSubrange), c.readOffset)\n\t}\n\n\tif len(p) < toCopy {\n\t\ttoCopy = len(p)\n\t}\n\tif c.remaining < int64(toCopy) {\n\t\ttoCopy = int(c.remaining) // Conversion is safe, c.remaining is small enough.\n\t}\n\n\tcopy(p, currentSubrange[offsetInSubrange:offsetInSubrange+toCopy])\n\tc.readOffset += int64(toCopy)","sourceCodeStart":518,"sourceCodeEnd":554,"githubUrl":"https://github.com/thanos-io/thanos/blob/35b8b991177def87ed52dcf10f9b6d87f07282c8/pkg/store/cache/caching_bucket.go#L518-L554","documentation":"This error wraps any failure from subrangeAt while reading cached object data. It reports the reader's current logical read offset (c.readOffset) so the developer can tell which position in the cached object could not be resolved to a subrange. It is thrown by subrangesReader.Read in Thanos's caching bucket layer when the internal subrange index is inconsistent.","triggerScenarios":"Calling Read on a reader obtained from a caching bucket when c.subranges has no entry for the subrange-aligned offset derived from c.readOffset (c.offsetsKeys lacks the computed key), e.g. after internal state corruption or a partially populated subrange map.","commonSituations":"Seen when debugging Thanos caching-bucket issues: cache entries evicted or truncated inconsistently, concurrent use of a single subrangesReader across goroutines, or version incompatibilities in cached data layout.","solutions":["Check that the reader is not shared between goroutines without synchronization","Verify the cache backend is healthy and entries were not evicted/truncated mid-read","Log c.readOffset, c.subrangeSize and available subrange keys to diagnose the mismatch","Update Thanos to the latest patch release; known subrange bugs have been fixed","As a workaround, disable the caching bucket for this reader path (use the plain bucket)"],"exampleFix":"// before\nn, err := r.Read(buf) // panics/errors deep in subrangeAt\n// after\nif r, ok := r.(*storecache.SubrangesReader); ok {\n    // use a fresh reader per request and limit reads to advertised size\n}\nn, err := io.ReadFull(freshReader, buf[:min(len(buf), size)])","handlingStrategy":"try-catch","validationCode":"if reader == nil || objectSize <= 0 { return errors.New(\"invalid reader or size\") }","typeGuard":"func usableReader(r io.Reader, size int64) bool { return r != nil && size > 0 }","tryCatchPattern":"n, err := reader.Read(buf)\nif err != nil {\n    var wrapped interface{ Cause() error }\n    if errors.As(err, &cause) && strings.Contains(err.Error(), \"read position:\") {\n        // fall back to a fresh GetRange for the failed offset\n    }\n    return err\n}","preventionTips":["Use one reader per goroutine; never share subrangesReader concurrently","Keep Thanos components on the same version","Monitor cache eviction metrics and backend truncation","Bound reads to the advertised object size"],"tags":["go","cache","thanos","caching-bucket"],"backgroundTag":"resource-not-found","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"}