{"record":{"id":"7a44d02b974ba417","repo":"thanos-io/thanos","slug":"topostinggroup","errorCode":null,"errorMessage":"toPostingGroup","messagePattern":"toPostingGroup","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/store/bucket.go","lineNumber":2900,"sourceCode":"\n\tpgs := make([]*postingGroup, 0, len(matchersMap))\n\t// NOTE: Derived from tsdb.PostingsForMatchers.\n\tfor _, values := range matchersMap {\n\t\tvar (\n\t\t\tmergedPG     *postingGroup\n\t\t\tpg           *postingGroup\n\t\t\tvals         []string\n\t\t\terr          error\n\t\t\tvaluesCached bool\n\t\t)\n\t\tlvalsFunc := lvalsFn\n\t\tmatchers := make([]*labels.Matcher, 0, len(vals))\n\t\t// Merge PostingGroups with the same matcher into 1 to\n\t\t// avoid fetching duplicate postings.\n\t\tfor _, val := range values {\n\t\t\tpg, vals, err = toPostingGroup(ctx, lvalsFunc, val)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, errors.Wrap(err, \"toPostingGroup\")\n\t\t\t}\n\t\t\t// Cache label values because label name is the same.\n\t\t\tif !valuesCached && vals != nil {\n\t\t\t\tlvals := vals\n\t\t\t\tlvalsFunc = func(_ string) ([]string, error) {\n\t\t\t\t\treturn lvals, nil\n\t\t\t\t}\n\t\t\t\tvaluesCached = true\n\t\t\t}\n\n\t\t\t// If this groups adds nothing, it's an empty group. We can shortcut this, since intersection with empty\n\t\t\t// postings would return no postings anyway.\n\t\t\t// E.g. label=\"non-existing-value\" returns empty group.\n\t\t\tif !pg.addAll && len(pg.addKeys) == 0 {\n\t\t\t\treturn nil, nil\n\t\t\t}\n\t\t\tif mergedPG == nil {\n\t\t\t\tmergedPG = pg","sourceCodeStart":2882,"sourceCodeEnd":2918,"githubUrl":"https://github.com/thanos-io/thanos/blob/35b8b991177def87ed52dcf10f9b6d87f07282c8/pkg/store/bucket.go#L2882-L2918","documentation":"In matchersToPostingGroups, matchers with multiple values (e.g. from regex expansion or set matchers) are merged, and each value is converted into a posting group via toPostingGroup, which resolves label values through the provided lvalsFunc (possibly hitting the index/bucket). Any per-value failure is wrapped as 'toPostingGroup'. It means a single matcher value could not be turned into a posting group fetch.","triggerScenarios":"toPostingGroup(ctx, lvalsFunc, val) errors while expanding one value of a multi-valued matcher — the label-values lookup fails (index header read error, lazy bucket fetch failure).","commonSituations":"Queries using regex/set matchers (foo=~\"a|b|c\") where resolving candidate values requires bucket-backed label values and storage fails; stale index-header caches; S3 throttling during value expansion.","solutions":["Inspect the wrapped inner error to distinguish storage failure from index corruption.","Retry the query for transient object-store errors.","Refresh store-gateway index-header caches/reload blocks.","Rewrite the matcher with explicit values (foo in {a,b,c}) to avoid expensive value expansion."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// ensure lvalsFunc never returns error for cached names\nlvalsFunc := func(name string) ([]string, error) {\n\tif v, ok := cache[name]; ok { return v, nil }\n\treturn indexHeader.LabelValues(ctx, name)\n}","typeGuard":null,"tryCatchPattern":"if err != nil {\n\tif isTransient(err) { /* retry value expansion */ }\n\treturn nil, errors.Wrap(err, \"toPostingGroup\")\n}","preventionTips":["Cache label values per block to cut bucket round-trips","Prefer set matchers with explicit values","Retry transient storage errors during value expansion"],"tags":["postings","matchers","thanos-store-gateway"],"backgroundTag":"database-query-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"}