{"record":{"id":"9222987cf2dc0b58","repo":"thanos-io/thanos","slug":"sending-targets-error-to-server-v","errorCode":null,"errorMessage":"sending targets error to server %v","messagePattern":"sending targets error to server (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/targets/proxy.go","lineNumber":120,"sourceCode":"\t\t// Not an error if response strategy is warning.\n\t\treturn nil\n\t}\n\n\tfor {\n\t\ttarget, err := targets.Recv()\n\t\tif err == io.EOF {\n\t\t\treturn nil\n\t\t}\n\n\t\tif err != nil {\n\t\t\terr = errors.Wrapf(err, \"receiving targets from targets client %v\", stream.client)\n\n\t\t\tif stream.request.PartialResponseStrategy == storepb.PartialResponseStrategy_ABORT {\n\t\t\t\treturn err\n\t\t\t}\n\n\t\t\tif err := stream.server.Send(targetspb.NewWarningTargetsResponse(err)); err != nil {\n\t\t\t\treturn errors.Wrapf(err, \"sending targets error to server %v\", stream.server)\n\t\t\t}\n\t\t\t// Not an error if response strategy is warning.\n\t\t\treturn nil\n\t\t}\n\n\t\tif w := target.GetWarning(); w != \"\" {\n\t\t\tif err := stream.server.Send(targetspb.NewWarningTargetsResponse(errors.New(w))); err != nil {\n\t\t\t\treturn errors.Wrapf(err, \"sending targets warning to server %v\", stream.server)\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\n\t\tselect {\n\t\tcase stream.channel <- target.GetTargets():\n\t\tcase <-ctx.Done():\n\t\t\treturn ctx.Err()\n\t\t}\n\t}","sourceCodeStart":102,"sourceCodeEnd":138,"githubUrl":"https://github.com/thanos-io/thanos/blob/35b8b991177def87ed52dcf10f9b6d87f07282c8/pkg/targets/proxy.go#L102-L138","documentation":"This error is thrown when, after receiving a targets error from the upstream client under the WARNING partial-response strategy, the proxy fails to send the error back to the caller as a warning TargetsResponse. It wraps the Send failure on the downstream gRPC server stream.","triggerScenarios":"In receive(), after wrapping a Recv error, PartialResponseStrategy is not ABORT, and stream.server.Send(targetspb.NewWarningTargetsResponse(err)) returns an error (client disconnected, context canceled, broken stream).","commonSituations":"The querying client canceled the request or timed out while the upstream error was being relayed; gRPC stream broken mid-response; client process restarted.","solutions":["Inspect the wrapped cause for stream cancellation or broken pipe; the original upstream error is likely secondary.","Check whether the downstream client (query frontend/UI) is canceling requests and why (timeout, user abort).","Ensure the gRPC connection to the client is healthy and no proxies/LBs terminate idle streams.","This is mostly unavoidable cleanup noise when clients disconnect; add retry/backoff at the caller instead."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"if err := stream.server.Send(resp); err != nil {\n    if errors.Is(errors.Cause(err), context.Canceled) {\n        return nil // client went away, not actionable\n    }\n    return err\n}","preventionTips":["Treat client cancellation as expected noise","Set LB/gateway idle timeouts longer than query timeouts","Log the wrapped cause, not just the wrapper"],"tags":["grpc","streaming","broken-pipe","thanos-targets"],"backgroundTag":"broken-pipe","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"}