{"record":{"id":"f6feec981b44a6ed","repo":"googleapis/mcp-toolbox","slug":"failed-to-send-request-w-f6feec","errorCode":null,"errorMessage":"failed to send request: %w","messagePattern":"failed to send request: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/tools/looker/lookerconversationalanalytics/lookerconversationalanalytics.go","lineNumber":441,"sourceCode":"}\n\nfunc getStream(ctx context.Context, client *http.Client, url string, payload CAPayload, headers map[string]string) ([]map[string]any, error) {\n\tpayloadBytes, err := json.Marshal(payload)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to marshal payload: %w\", err)\n\t}\n\n\treq, err := http.NewRequest(\"POST\", url, bytes.NewBuffer(payloadBytes))\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to create request: %w\", err)\n\t}\n\tfor k, v := range headers {\n\t\treq.Header.Set(k, v)\n\t}\n\n\tresp, err := client.Do(req)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to send request: %w\", err)\n\t}\n\tdefer resp.Body.Close()\n\n\tif resp.StatusCode != http.StatusOK {\n\t\tbody, _ := io.ReadAll(resp.Body)\n\t\treturn nil, fmt.Errorf(\"API returned non-200 status: %d %s\", resp.StatusCode, string(body))\n\t}\n\n\tvar messages []map[string]any\n\tdecoder := json.NewDecoder(resp.Body)\n\n\t// The response is a JSON array, so we read the opening bracket.\n\tif _, err := decoder.Token(); err != nil {\n\t\tif err == io.EOF {\n\t\t\treturn nil, nil // Empty response is valid\n\t\t}\n\t\treturn nil, fmt.Errorf(\"error reading start of json array: %w\", err)\n\t}","sourceCodeStart":423,"sourceCodeEnd":459,"githubUrl":"https://github.com/googleapis/mcp-toolbox/blob/8cc6e09de2ad7b8bffc77751799585a1401a48eb/internal/tools/looker/lookerconversationalanalytics/lookerconversationalanalytics.go#L423-L459","documentation":"This error wraps a low-level network/transport failure that occurred while the Looker Conversational Analytics tool was executing its HTTP request to the Google Cloud API via client.Do(req). It appears with the underlying error (e.g. DNS failure, TLS handshake error, context deadline exceeded) appended via %w, so the wrapped cause is always present in the message. The library throws it because the request never received an HTTP response at all — it is not about a bad status code.","triggerScenarios":"Any invocation of the looker-conversational-analytics tool where http.Client.Do fails: DNS resolution failure, connection refused/reset, TLS errors, or the request context being cancelled/timed out before a response arrives.","commonSituations":"No outbound network access or a proxy/firewall blocking googleapis.com; running in an environment with a short context timeout; misconfigured HTTPS_PROXY; IPv6/DNS issues in containers; transient network blips.","solutions":["Read the wrapped error after '%w' to identify the root cause (DNS vs TLS vs timeout).","Verify outbound network connectivity to the Looker/API endpoint from the host running the toolbox.","If the wrapped error is 'context deadline exceeded' or 'context canceled', increase the caller's timeout or check for premature cancellation upstream.","Check proxy environment variables (HTTP_PROXY/HTTPS_PROXY/NO_PROXY) are correct.","Retry the request, as some failures are transient."],"exampleFix":"// before: context with no deadline control, fails on slow networks\nctx := r.Context()\nresp, err := client.Do(req)\n// after: give the request an explicit budget\nctx, cancel := context.WithTimeout(r.Context(), 60*time.Second)\ndefer cancel()\nreq = req.WithContext(ctx)\nresp, err := client.Do(req)","handlingStrategy":"retry","validationCode":"// Go: preflight connectivity before invoking\nfunc canReachEndpoint(ctx context.Context, url string) error {\n    req, _ := http.NewRequestWithContext(ctx, http.MethodHead, url, nil)\n    _, err := http.DefaultClient.Do(req)\n    return err\n}","typeGuard":"// Go: extract and classify the wrapped transport error\nimport (\"errors\"; \"net\"; \"net/url\"; \"context\")\nfunc isNetworkErr(err error) bool {\n    var dnsErr *net.DNSError\n    var opErr *net.OpError\n    return errors.As(err, &dnsErr) || errors.As(err, &opErr) || errors.Is(err, context.DeadlineExceeded)\n}","tryCatchPattern":"err := invokeTool(ctx, req)\nif err != nil && strings.Contains(err.Error(), \"failed to send request\") {\n    if isNetworkErr(err) {\n        // backoff-retry with jitter\n        time.Sleep(backoff)\n        err = invokeTool(ctx, req)\n    }\n    if err != nil { log.Printf(\"transport error: %v\", err) }\n}","preventionTips":["Set explicit, generous context timeouts for LLM-facing API calls.","Verify egress/proxy configuration (HTTP_PROXY/HTTPS_PROXY/NO_PROXY) in the deployment environment.","Monitor DNS and TLS health in containers/k8s.","Implement bounded retry with exponential backoff for transient transport errors."],"tags":["network","http","looker","transient"],"backgroundTag":"http-request-failed","analyzedSha":"8cc6e09de2ad7b8bffc77751799585a1401a48eb","analyzedAt":"2026-09-05T01:10:36.887Z","contentChangedAt":"2026-09-05T01:10:36.887Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}