{"record":{"id":"eb7d7232fb6efe4d","repo":"thanos-io/thanos","slug":"failed-to-send-series","errorCode":null,"errorMessage":"failed to send series","messagePattern":"failed to send series","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/store/limiter.go","lineNumber":187,"sourceCode":"func (i *limitedServer) Send(response *storepb.SeriesResponse) error {\n\tvar seriesCount, chunksCount uint64\n\tif series := response.GetSeries(); series != nil {\n\t\tseriesCount = 1\n\t\tchunksCount = uint64(len(series.Chunks))\n\t} else if batch := response.GetBatch(); batch != nil {\n\t\tfor _, series := range batch.Series {\n\t\t\tif series == nil {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tseriesCount++\n\t\t\tchunksCount += uint64(len(series.Chunks))\n\t\t}\n\t} else {\n\t\treturn i.Store_SeriesServer.Send(response)\n\t}\n\n\tif err := i.seriesLimiter.Reserve(seriesCount); err != nil {\n\t\treturn errors.Wrapf(err, \"failed to send series\")\n\t}\n\tif err := i.samplesLimiter.Reserve(chunksCount * MaxSamplesPerChunk); err != nil {\n\t\treturn errors.Wrapf(err, \"failed to send samples\")\n\t}\n\n\treturn i.Store_SeriesServer.Send(response)\n}\n","sourceCodeStart":169,"sourceCodeEnd":195,"githubUrl":"https://github.com/thanos-io/thanos/blob/35b8b991177def87ed52dcf10f9b6d87f07282c8/pkg/store/limiter.go#L169-L195","documentation":"limiterStore's Send wraps the seriesLimiter.Reserve error with \"failed to send series\" before forwarding a SeriesSet response. It means the number of series in the outgoing response would exceed the configured series limit, so the response is rejected instead of sent.","triggerScenarios":"Streaming a Series response where seriesCount added to previous reservations exceeds the series limiter's limit (Reserve fails, error wrapped by errors.Wrapf).","commonSituations":"Queries with very broad label selectors hitting --store.series-limit; dashboards issuing single queries over many series; limit set to a small value in thanos-query/store-gateway configuration.","solutions":["Narrow the query matchers or time range to reduce selected series count.","Increase --store.series-limit on the relevant component.","Use partial-response / sharding to split the query across smaller requests.","Aggregate at the query-frontend to avoid unbounded fan-out."],"exampleFix":"// before\nquery(query, matchers *[^.*])\n// after\nquery(query, matchers limited to specific {job=\"prometheus\", instance=~\"specific-host.*\"})","handlingStrategy":"fallback","validationCode":"// pre-check cardinality via the query frontend before issuing Series\nseries, _ := promAPI.Series(ctx, matchers...)\nif len(series) > seriesLimit { /* narrow matchers */ }","typeGuard":null,"tryCatchPattern":"if err != nil && strings.Contains(err.Error(), \"failed to send series\") {\n  // split the query (shard by label or time) and retry per-shard\n}","preventionTips":["Keep series-limit above your dashboard worst-case cardinality","Use query sharding for high-cardinality selectors","Prefer -36h time ranges over multi-day single queries"],"tags":["go","limits","series"],"backgroundTag":"rate-limit-exceeded","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"}