{"record":{"id":"708bd69b7f94de73","repo":"Tencent/WeKnora","slug":"failed-to-execute-metaso-request-w","errorCode":null,"errorMessage":"failed to execute Metaso request: %w","messagePattern":"failed to execute Metaso request: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/infrastructure/web_search/metaso.go","lineNumber":104,"sourceCode":"\tbody, err := json.Marshal(metasoSearchRequest{\n\t\tQuery: query, Scope: p.scope, Size: maxResults,\n\t\tIncludeSummary: true, IncludeRawContent: false, ConciseSnippet: true,\n\t})\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to marshal Metaso request: %w\", err)\n\t}\n\treq, err := http.NewRequestWithContext(ctx, http.MethodPost, p.baseURL, bytes.NewReader(body))\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to create Metaso request: %w\", err)\n\t}\n\treq.Header.Set(\"Authorization\", \"Bearer \"+p.apiKey)\n\treq.Header.Set(\"Accept\", \"application/json\")\n\treq.Header.Set(\"Content-Type\", \"application/json\")\n\n\tlogger.Infof(ctx, \"[WebSearch][Metaso] query=%q maxResults=%d scope=%s\", query, maxResults, p.scope)\n\tresp, err := p.client.Do(req)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to execute Metaso request: %w\", err)\n\t}\n\tdefer resp.Body.Close()\n\trespBody, err := readMetasoResponseBody(resp.Body)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif resp.StatusCode != http.StatusOK {\n\t\treturn nil, metasoHTTPError(resp.StatusCode, respBody)\n\t}\n\n\tvar response metasoSearchResponse\n\tif err := json.Unmarshal(respBody, &response); err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to unmarshal Metaso response: %w\", err)\n\t}\n\tresults := make([]*types.WebSearchResult, 0, len(response.Webpages))\n\tfor _, item := range response.Webpages {\n\t\tif strings.TrimSpace(item.Title) == \"\" && strings.TrimSpace(item.Link) == \"\" {\n\t\t\tcontinue","sourceCodeStart":86,"sourceCodeEnd":122,"githubUrl":"https://github.com/Tencent/WeKnora/blob/988cbb03305e055d8ebb7d46d9ac6cc0803cd074/internal/infrastructure/web_search/metaso.go#L86-L122","documentation":"Returned by MetasoProvider.Search when p.client.Do(req) fails, i.e. the HTTP request could not be completed at the transport level. This wraps DNS failures, connection refused/reset, TLS errors, and context cancellation or deadline exceeded. Since Metaso requires the API call to succeed, the search aborts with the underlying cause wrapped via %w.","triggerScenarios":"Search (internal/infrastructure/web_search/metaso.go:104): client.Do returns an error — network unreachable, DNS resolution failure for the Metaso host, connection refused (server down/wrong port), TLS handshake failure, or ctx deadline exceeded/canceled mid-request.","commonSituations":"No internet or DNS outage; corporate firewall/proxy blocking api.metaso.cn; wrong baseURL host; short context timeout cutting off a slow response; certificate issues behind a TLS-intercepting proxy.","solutions":["Unwrap the error: check errors.Is(err, context.DeadlineExceeded) for timeouts, or use net.Error.Timeout() and *url.Error to identify DNS/connect/TLS causes.","Verify basic connectivity to the Metaso endpoint (curl the base URL) and DNS resolution from the host running the app.","Increase the context/client timeout if the deadline is shorter than Metaso's response time, and retry with backoff for transient failures.","Check proxy/firewall settings (HTTP_PROXY/HTTPS_PROXY) and TLS interception certificates.","Confirm the base URL host/port is correct if you run a custom endpoint."],"exampleFix":"// before: no timeout differentiation or retry\nresp, err := p.client.Do(req)\nif err != nil { return nil, err }\n\n// after: timeout-aware retry\nvar resp *http.Response\nfor attempt := 0; attempt < 3; attempt++ {\n    resp, err = p.client.Do(req)\n    if err == nil { break }\n    var ne net.Error\n    if errors.As(err, &ne) && ne.Timeout() {\n        time.Sleep(time.Duration(attempt+1) * time.Second)\n        continue\n    }\n    break\n}\nif err != nil { return nil, fmt.Errorf(\"failed to execute Metaso request: %w\", err) }","handlingStrategy":"retry","validationCode":"ctx, cancel := context.WithTimeout(ctx, 30*time.Second)\ndefer cancel()\n\n// pre-flight reachability check at startup:\nif err := net.DialTimeout(\"tcp\", \"api.metaso.cn:443\", 5*time.Second); err != nil {\n    log.Printf(\"warning: Metaso endpoint unreachable at startup: %v\", err)\n}","typeGuard":null,"tryCatchPattern":"resp, err := p.client.Do(req)\nif err != nil {\n    var ne net.Error\n    switch {\n    case errors.As(err, &ne) && ne.Timeout():\n        return nil, fmt.Errorf(\"metaso request timed out, retry advised: %w\", err)\n    case errors.Is(err, context.Canceled):\n        return nil, err // caller canceled — do not retry\n    default:\n        return nil, fmt.Errorf(\"transient network failure: %w\", err)\n    }\n}","preventionTips":["Set explicit client timeouts and context deadlines sized for search latency.","Implement exponential backoff retries for idempotent search calls.","Monitor egress connectivity/DNS in production and alert on failures.","Document proxy settings (HTTPS_PROXY) needed in restricted networks and verify TLS trust."],"tags":["network","http","timeout","dns","web-search"],"backgroundTag":"http-request-failed","analyzedSha":"988cbb03305e055d8ebb7d46d9ac6cc0803cd074","analyzedAt":"2026-09-02T14:41:08.344Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}