{"record":{"id":"037eda195248feba","repo":"vxcontrol/pentagi","slug":"google-search-failed-w","errorCode":null,"errorMessage":"google search failed: %w","messagePattern":"google search failed: %w","errorType":"exception","errorClass":"RetryableError","httpStatus":null,"severity":"warning","filePath":"backend/pkg/tools/searchers/google.go","lineNumber":90,"sourceCode":"\t\t\t}),\n\t\t)\n\n\t\tobs.LogErrorOrCancel(logger, err, \"failed to search in google\")\n\t\treturn \"\", classifyGoogleError(err)\n\t}\n\n\treturn result, nil\n}\n\n// classifyGoogleError maps a Google Custom Search failure to a retryable/fatal error.\n// A *googleapi.Error carries the upstream HTTP status (429/5xx retryable, 4xx fatal);\n// anything else is a transport-level failure, which may clear on retry.\nfunc classifyGoogleError(err error) error {\n\tvar gerr *googleapi.Error\n\tif errors.As(err, &gerr) {\n\t\treturn ClassifyHTTPStatus(gerr.Code, \"google search failed\")\n\t}\n\treturn Retryable(fmt.Errorf(\"google search failed: %w\", err), 0)\n}\n\nfunc (g *google) search(ctx context.Context, svc *customsearch.Service, query string, numResults int64) (string, error) {\n\tresp, err := svc.Cse.List().Context(ctx).Cx(g.cxKey()).Q(query).Lr(g.lrKey()).Num(numResults).Do()\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"failed to do request: %w\", err)\n\t}\n\n\treturn g.formatResults(resp), nil\n}\n\nfunc (g *google) formatResults(res *customsearch.Search) string {\n\tvar writer strings.Builder\n\tfor i, item := range res.Items {\n\t\twriter.WriteString(fmt.Sprintf(\"# %d. %s\\n\\n\", i+1, item.Title))\n\t\twriter.WriteString(fmt.Sprintf(\"## URL\\n%s\\n\\n\", item.Link))\n\t\twriter.WriteString(fmt.Sprintf(\"## Snippet\\n\\n%s\\n\\n\", item.Snippet))\n\t}","sourceCodeStart":72,"sourceCodeEnd":108,"githubUrl":"https://github.com/vxcontrol/pentagi/blob/ea665308baaff015b226f308438a68d929d0f29b/backend/pkg/tools/searchers/google.go#L72-L108","documentation":"classifyGoogleError wraps any Google Custom Search failure that is NOT a *googleapi.Error into Retryable(fmt.Errorf(\"google search failed: %w\", err)). This is the fallback branch: googleapi.Error means the server answered with an HTTP status (classified via ClassifyHTTPStatus); anything else — DNS failure, TLS error, connection refused, context deadline, JSON decoding — lands here as potentially transient.","triggerScenarios":"svc.Cse.List()...Do() returns a non-googleapi error: network unreachable, DNS resolution failure for www.googleapis.com, TLS handshake failure through the proxy, or ctx deadline exceeded mid-request.","commonSituations":"Backend container without egress to googleapis.com; corporate proxy requiring auth; short context timeouts canceling slow requests; intermittent DNS failures in Docker networks.","solutions":["Inspect the wrapped cause to distinguish network vs timeout vs TLS problems","Verify container egress/proxy settings for www.googleapis.com:443","Increase the request context timeout if deadline-exceeded is the cause","Retry: the error is Retryable so the orchestrator's fallback strategy handles transient blips automatically"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// preflight DNS/egress\nconn, err := net.DialTimeout(\"tcp\", \"www.googleapis.com:443\", 5*time.Second)\nif err != nil { // no egress: expect 'google search failed' retries\n}","typeGuard":"var gerr *googleapi.Error\nfunc isHTTPLevel(err error) bool { return errors.As(err, &googleapi.Error{} as any) != false && errors.As(err, &gerr) }\n// simpler: func isTransportError(err error) bool { return !errors.As(err, new(*googleapi.Error)) }","tryCatchPattern":"result, err := googleSearcher.Handle(ctx, req)\nif err != nil {\n    if searchers.IsRetryable(err) {\n        return fallbackSearcher.Handle(ctx, req) // transport blip; another engine serves the query\n    }\n    return \"\", err\n}","preventionTips":["Guarantee container egress to www.googleapis.com:443 or configure a working proxy","Give requests generous context timeouts","Rely on the Retryable classification instead of implementing ad-hoc retries"],"tags":["google","customsearch","network","retryable"],"backgroundTag":"google-search-request-failed","analyzedSha":"ea665308baaff015b226f308438a68d929d0f29b","analyzedAt":"2026-09-01T14:16:31.421Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}