vxcontrol/pentagi · error
failed to create google search service: %v
Error message
failed to create google search service: %v
What it means
newSearchService returns 'failed to create google search service: %v' when customsearch.NewService(ctx, option.WithHTTPClient(client)) fails to initialize the Custom Search service from the supplied HTTP client. Handle wraps this into a Fatal error, so the orchestrator falls through to other engines. Initialization rarely fails at runtime — it typically indicates context or client problems rather than Google-side issues.
Source
Thrown at backend/pkg/tools/searchers/google.go:132
client, err := system.GetHTTPClient(g.cfg)
if err != nil {
return nil, fmt.Errorf("failed to create http client: %w", err)
}
// google.golang.org/api normally injects the API key through the HTTP transport it
// builds itself. But we MUST supply our own proxy/TLS client via WithHTTPClient, and
// WithHTTPClient takes precedence — it replaces that transport, so option.WithAPIKey
// is silently dropped and requests go out unauthenticated (HTTP 403 "unregistered
// caller"). Attach the key ourselves as the `key` query parameter (the documented
// Custom Search auth) by wrapping the proxy client's transport.
client.Transport = &googleAPIKeyTransport{
key: g.apiKey(),
base: client.Transport,
}
svc, err := customsearch.NewService(ctx, option.WithHTTPClient(client))
if err != nil {
return nil, fmt.Errorf("failed to create google search service: %v", err)
}
return svc, nil
}
// googleAPIKeyTransport attaches the Google API key as the `key` query parameter to
// every outgoing request, so authentication survives the proxy/TLS client that
// option.WithHTTPClient forces us to use (see newSearchService).
type googleAPIKeyTransport struct {
key string
base http.RoundTripper
}
func (t *googleAPIKeyTransport) RoundTrip(req *http.Request) (*http.Response, error) {
// Clone so the caller's request is never mutated.
r := req.Clone(req.Context())
q := r.URL.Query()
q.Set("key", t.key)View on GitHub (pinned to ea665308ba)
Solutions
- Check whether the incoming ctx was canceled before Handle ran; fix upstream timeouts
- Reuse a single customsearch.Service instance instead of rebuilding per query
- Verify the client passed via option.WithHTTPClient has a valid non-nil Transport (googleAPIKeyTransport falls back to http.DefaultTransport if base is nil)
- This is Fatal — no retry will help until the root cause is fixed
Example fix
// before: build service on every search
svc, err := customsearch.NewService(ctx, option.WithHTTPClient(client))
// after: build once and reuse
var svcOnce sync.Once
svcOnce.Do(func() { svc, svcErr = customsearch.NewService(context.Background(), option.WithHTTPClient(client)) }) Defensive patterns
Strategy: fallback
Validate before calling
// ensure the context is live before building the service
if ctx.Err() != nil {
// skip: NewService will fail on a canceled context
} Try / catch
svc, err := g.newSearchService(ctx)
if err != nil {
return fallbackSearcher.Handle(ctx, req) // Fatal: retrying the same call won't help
} Prevention
- Build the customsearch.Service once and reuse it (sync.Once or at construction time)
- Never pass an already-canceled/short-deadline context into service construction
- Keep option.WithHTTPClient's client valid with a non-nil Transport
When it happens
Trigger: customsearch.NewService errors: the passed ctx is already canceled/deadline-exceeded, or the option.WithHTTPClient client is misconfigured (nil transport etc.). Note auth is handled manually via googleAPIKeyTransport, so NewService failure is not about the API key.
Common situations: Calling Handle with an expired request context; constructing the service per-request under tight timeouts instead of reusing it; odd proxy clients whose transport behaves unexpectedly during SDK init.
Related errors
- failed to create google search service: %w
- google search failed: %w
- failed to do request: %w
- could not create Google OpenID client: %w
- id_token is not present in the token
AI-assisted analysis of vxcontrol/pentagi@ea665308ba (2026-09-01).
Data as JSON: /api/errors/c494b044a520754b.
Report an issue: GitHub.