{"record":{"id":"ee36e474d8ab681c","repo":"thanos-io/thanos","slug":"reading-series-length-failed","errorCode":null,"errorMessage":"reading series length failed","messagePattern":"reading series length failed","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/store/bucket.go","lineNumber":3411,"sourceCode":"\tif err := bytesLimiter.ReserveWithType(uint64(end-start), SeriesFetched); err != nil {\n\t\treturn httpgrpc.Errorf(int(codes.ResourceExhausted), \"exceeded bytes limit while fetching series: %s\", err)\n\t}\n\n\tb, err := r.block.readIndexRange(ctx, int64(start), int64(end-start), r.logger)\n\tif err != nil {\n\t\treturn errors.Wrap(err, \"read series range\")\n\t}\n\n\tstats.seriesFetchCount++\n\tstats.SeriesFetchDurationSum += time.Since(begin)\n\tstats.add(SeriesFetched, len(ids), int(end-start))\n\n\tfor i, id := range ids {\n\t\tc := b[uint64(id)-start:]\n\n\t\tl, n := binary.Uvarint(c)\n\t\tif n < 1 {\n\t\t\treturn errors.New(\"reading series length failed\")\n\t\t}\n\t\tif len(c) < n+int(l) {\n\t\t\tif i == 0 && refetch {\n\t\t\t\treturn errors.Errorf(\"invalid remaining size, even after refetch, remaining: %d, expected %d\", len(c), n+int(l))\n\t\t\t}\n\n\t\t\t// Inefficient, but should be rare.\n\t\t\tr.block.metrics.seriesRefetches.WithLabelValues(tenant).Inc()\n\t\t\tlevel.Warn(r.logger).Log(\"msg\", \"series size exceeded expected size; refetching\", \"id\", id, \"series length\", n+int(l), \"maxSeriesSize\", r.block.estimatedMaxSeriesSize)\n\n\t\t\t// Fetch plus to get the size of next one if exists.\n\t\t\treturn r.loadSeries(ctx, ids[i:], true, uint64(id), uint64(id)+uint64(n+int(l)+1), bytesLimiter, tenant)\n\t\t}\n\t\tc = c[n : n+int(l)]\n\t\tr.loadedSeriesMtx.Lock()\n\t\tr.loadedSeries[id] = c\n\t\tr.loadedSeriesMtx.Unlock()\n","sourceCodeStart":3393,"sourceCodeEnd":3429,"githubUrl":"https://github.com/thanos-io/thanos/blob/35b8b991177def87ed52dcf10f9b6d87f07282c8/pkg/store/bucket.go#L3393-L3429","documentation":"While decoding a fetched index byte range, each series entry begins with a uvarint length. binary.Uvarint returning n < 1 means the bytes at the expected offset do not even contain a valid length prefix, so the reader cannot parse the series record. This indicates the fetched range does not align with actual series data — i.e. corrupt, truncated, or stale index bytes.","triggerScenarios":"DecodeSeries parses b[uint64(id)-start:] and binary.Uvarint fails (n < 1): id offset outside the fetched range, truncated read from object storage/cache, or index bytes corrupted in cache.","commonSituations":"Corrupted entries in the external series cache (e.g. Redis truncation); a series ref (id) that does not belong to the fetched block/range; partially uploaded or corrupted index file in the bucket; cache entry written by a different block with the same ULID (rebuilt block reusing ULID).","solutions":["Clear/invalidate the series cache for the affected block (or flush the whole index cache) and retry","Verify the block's index integrity (thanos tools bucket verify); delete/re-upload the block if corrupt","Ensure series refs come from the same block's postings — a ref from another block produces bogus offsets","Check that block ULIDs are unique (rebuilt blocks must not reuse ULIDs) to avoid cache key collisions"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"if uint64(id) < start || uint64(id)-start >= uint64(len(b)) {\n\treturn errors.Errorf(\"series id %d outside fetched range [%d,%d)\", id, start, len(b))\n}","typeGuard":"func offsetInRange(b []byte, id, start uint64) bool { return id >= start && id-start < uint64(len(b)) }","tryCatchPattern":"l, n := binary.Uvarint(c)\nif n < 1 {\n\tlogger.Warn(\"invalid series record; invalidating cache entry\", \"id\", id)\n\tseriesCache.Invalidate(blockMeta.ULID, id)\n\treturn retryFetchSeries(ctx, ids) // refetch without cache\n}","preventionTips":["Flush series cache when rebuilding blocks (never reuse ULIDs)","Validate blocks with bucket verify before serving","Ensure refs are looked up against the same block","Limit cache backends to binary-safe value handling"],"tags":["thanos","series","decoding","corruption","index"],"backgroundTag":"invalid-argument-format","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"}