{"record":{"id":"caa7ceb9b5a13cc8","repo":"thanos-io/thanos","slug":"encoding-with-snappy","errorCode":null,"errorMessage":"encoding with snappy","messagePattern":"encoding with snappy","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/store/bucket.go","lineNumber":3233,"sourceCode":"\t\t\t}\n\t\t\tdefer runutil.CloseWithLogOnErr(r.logger, partReader, \"readIndexRange close range reader\")\n\t\t\tbrdr.Reset(partReader)\n\n\t\t\trdr := newPostingsReaderBuilder(ctx, brdr, ptrs[i:j], start, length)\n\n\t\t\tstats.postingsFetchCount++\n\t\t\tstats.add(PostingsFetched, j-i, int(length))\n\n\t\t\tfor rdr.Next() {\n\t\t\t\tdiffVarintPostings, postingsCount, keyID := rdr.AtDiffVarint()\n\n\t\t\t\toutput[keyID] = newDiffVarintPostings(diffVarintPostings, nil)\n\n\t\t\t\tstartCompression := time.Now()\n\t\t\t\tdataToCache, err := snappyStreamedEncode(int(postingsCount), diffVarintPostings)\n\t\t\t\tif err != nil {\n\t\t\t\t\tstats.cachedPostingsCompressionErrors += 1\n\t\t\t\t\treturn errors.Wrap(err, \"encoding with snappy\")\n\t\t\t\t}\n\n\t\t\t\tstats.cachedPostingsCompressions += 1\n\t\t\t\tstats.CachedPostingsOriginalSizeSum += units.Base2Bytes(len(diffVarintPostings))\n\t\t\t\tstats.CachedPostingsCompressedSizeSum += units.Base2Bytes(len(dataToCache))\n\t\t\t\tstats.CachedPostingsCompressionTimeSum += time.Since(startCompression)\n\t\t\t\tstats.add(PostingsTouched, 1, len(diffVarintPostings))\n\n\t\t\t\tr.block.indexCache.StorePostings(r.block.meta.ULID, keys[keyID], dataToCache, tenant)\n\t\t\t}\n\n\t\t\tstats.PostingsFetchDurationSum += time.Since(begin)\n\n\t\t\tif err := rdr.Error(); err != nil {\n\t\t\t\treturn errors.Wrap(err, \"reading postings\")\n\t\t\t}\n\t\t\treturn nil\n\t\t})","sourceCodeStart":3215,"sourceCodeEnd":3251,"githubUrl":"https://github.com/thanos-io/thanos/blob/35b8b991177def87ed52dcf10f9b6d87f07282c8/pkg/store/bucket.go#L3215-L3251","documentation":"Before storing fetched postings into the index cache, the reader compresses them with streamed snappy (snappyStreamedEncode). If that compression fails, the postings were read fine but cannot be cached, and the error aborts this postings-fetch goroutine. This is rare and points to a snappy encoder-level failure (e.g. corrupt in-memory buffer or unsupported size) rather than to user input.","triggerScenarios":"snappyStreamedEncode(postingsCount, diffVarintPostings) returns an error during cache-fill after successfully reading postings from object storage; typically internal buffer/stream error in the snappy streaming encoder.","commonSituations":"Very large postings lists stressing the streaming encoder; corrupted in-memory diffVarint postings buffer; a Thanos/snappy library version incompatibility.","solutions":["Retry the query — this is usually transient and postings will be re-read from storage","If persistent, disable postings caching (or lower cached postings limits) to stop encoding failures from failing queries","Upgrade Thanos to a version matching the vendored golang/snappy library and check for known encoding bugs","Report/persist stats.cachedPostingsCompressionErrors to correlate with specific blocks or posting sizes"],"exampleFix":"// before\ndataToCache, err := snappyStreamedEncode(int(postingsCount), diffVarintPostings)\nif err != nil {\n\tstats.cachedPostingsCompressionErrors += 1\n\treturn errors.Wrap(err, \"encoding with snappy\")\n}\n// after\ndataToCache, err := snappyStreamedEncode(int(postingsCount), diffVarintPostings)\nif err != nil {\n\tstats.cachedPostingsCompressionErrors += 1\n\tlevel.Warn(logger).Log(\"msg\", \"skipping postings cache fill; encode failed\", \"err\", err)\n\treturn nil // serve result without caching instead of failing the query\n}","handlingStrategy":"fallback","validationCode":"if postingsCount == 0 || len(diffVarintPostings) == 0 || len(diffVarintPostings) > maxCacheEntrySize {\n\t// skip caching; serve postings without cache fill\n}","typeGuard":"func canCachePostings(count int, blob []byte) bool { return count > 0 && len(blob) > 0 && len(blob) <= maxCacheEntrySize }","tryCatchPattern":"dataToCache, err := snappyStreamedEncode(postingsCount, diffVarintPostings)\nif err != nil {\n\tstats.cachedPostingsCompressionErrors += 1\n\tlogger.Warn(\"snappy encode failed; skipping cache fill\", \"err\", err)\n\treturn nil // do not fail the query for a cache-fill problem\n}","preventionTips":["Never let cache-fill failures fail user queries — log and skip","Keep Thanos and golang/snappy versions consistent across the fleet","Cap cached postings entry sizes","Track cachedPostingsCompressionErrors in metrics"],"tags":["thanos","snappy","cache","compression","index"],"backgroundTag":"snappy-compression-failed","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"}