{"record":{"id":"cc13b7cfae4105bd","repo":"thanos-io/thanos","slug":"proxy-rules","errorCode":null,"errorMessage":"proxy Rules","messagePattern":"proxy Rules","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/rules/rules.go","lineNumber":61,"sourceCode":"\tc := &GRPCClient{\n\t\tproxy:         rs,\n\t\treplicaLabels: map[string]struct{}{},\n\t}\n\n\tfor _, label := range replicaLabels {\n\t\tc.replicaLabels[label] = struct{}{}\n\t}\n\treturn c\n}\n\nfunc (rr *GRPCClient) Rules(ctx context.Context, req *rulespb.RulesRequest) (*rulespb.RuleGroups, annotations.Annotations, error) {\n\tspan, ctx := tracing.StartSpan(ctx, \"rules_request\")\n\tdefer span.Finish()\n\n\tresp := &rulesServer{ctx: ctx}\n\n\tif err := rr.proxy.Rules(req, resp); err != nil {\n\t\treturn nil, nil, errors.Wrap(err, \"proxy Rules\")\n\t}\n\n\tvar err error\n\tmatcherSets := make([][]*labels.Matcher, len(req.MatcherString))\n\tfor i, s := range req.MatcherString {\n\t\tmatcherSets[i], err = extpromql.ParseMetricSelector(s)\n\t\tif err != nil {\n\t\t\treturn nil, nil, errors.Wrap(err, \"parser ParseMetricSelector\")\n\t\t}\n\t}\n\n\tresp.groups = filterRulesByMatchers(resp.groups, matcherSets)\n\tresp.groups = filterRulesByNamesAndFile(resp.groups, req.RuleName, req.RuleGroup, req.File)\n\n\t// TODO(bwplotka): Move to SortInterface with equal method and heap.\n\tresp.groups = dedupGroups(resp.groups)\n\tfor _, g := range resp.groups {\n\t\tg.Rules = dedupRules(g.Rules, rr.replicaLabels)","sourceCodeStart":43,"sourceCodeEnd":79,"githubUrl":"https://github.com/thanos-io/thanos/blob/35b8b991177def87ed52dcf10f9b6d87f07282c8/pkg/rules/rules.go#L43-L79","documentation":"The Rules gRPC handler wraps any error returned by rr.proxy.Rules(req, resp) — the call that fans the rules request out to underlying rule managers/upstream rulers — with the message 'proxy Rules'. The actual cause is in the wrapped error chain; this wrapper only marks the proxy stage of the request.","triggerScenarios":"Calling the Rules API (client.Rules or the gRPC Rules endpoint) when the internal proxy call fails: upstream ruler unreachable, context cancelled, or a rulesServer.Send error (e.g. 'no group') surfaces from resp.","commonSituations":"Querying rules while a backend ruler is down; request timeout against a slow upstream; a forwarded response violating the rulespb contract.","solutions":["Read the wrapped cause in the error chain and fix that specific failure first","Verify all upstream ruler endpoints are healthy and reachable","Retry the request with a longer context timeout if the upstream was slow"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"groups, warnings, err := client.Rules(ctx, req)\nif err != nil {\n    var proxyErr interface{ Unwrap() error }\n    if errors.As(err, &proxyErr) {\n        log.Printf(\"rules proxy failed: %v\", errors.Unwrap(err))\n    }\n    return err\n}","preventionTips":["Health-check upstream ruler endpoints before issuing requests","Set generous context timeouts for rules fan-out","Inspect the full wrapped error chain, not just the top message"],"tags":["grpc","proxy","rules"],"backgroundTag":"upstream-api-error","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"}