{"record":{"id":"73f249496adb1903","repo":"Tencent/WeKnora","slug":"api-key-is-required-for-google-provider-73f249","errorCode":null,"errorMessage":"API key is required for Google provider","messagePattern":"API key is required for Google provider","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/infrastructure/web_search/google.go","lineNumber":27,"sourceCode":"\t\"google.golang.org/api/option\"\n\n\t\"github.com/Tencent/WeKnora/internal/logger\"\n\t\"github.com/Tencent/WeKnora/internal/types\"\n\t\"github.com/Tencent/WeKnora/internal/types/interfaces\"\n)\n\n// GoogleProvider implements web search using Google Custom Search Engine API\ntype GoogleProvider struct {\n\tsrv      *customsearch.Service\n\tapiKey   string\n\tengineID string\n}\n\n// NewGoogleProvider creates a new Google provider from parameters (no environment variables).\n// The API endpoint is the official Google Custom Search endpoint — not tenant-configurable.\nfunc NewGoogleProvider(params types.WebSearchProviderParameters) (interfaces.WebSearchProvider, error) {\n\tif params.APIKey == \"\" {\n\t\treturn nil, fmt.Errorf(\"API key is required for Google provider\")\n\t}\n\tif params.EngineID == \"\" {\n\t\treturn nil, fmt.Errorf(\"engine ID is required for Google provider\")\n\t}\n\n\thttpClient, err := NewSearchHTTPClient(30*time.Second, params.ProxyURL)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tclientOpts := []option.ClientOption{\n\t\toption.WithAPIKey(params.APIKey),\n\t\toption.WithHTTPClient(httpClient),\n\t}\n\tsrv, err := customsearch.NewService(context.Background(), clientOpts...)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn &GoogleProvider{","sourceCodeStart":9,"sourceCodeEnd":45,"githubUrl":"https://github.com/Tencent/WeKnora/blob/988cbb03305e055d8ebb7d46d9ac6cc0803cd074/internal/infrastructure/web_search/google.go#L9-L45","documentation":"NewGoogleProvider requires a non-empty APIKey in the WebSearchProviderParameters and returns this error immediately at construction time if it is missing. The provider is built purely from parameters (no environment fallback), so the caller must supply the Google Custom Search API key explicitly.","triggerScenarios":"Calling NewGoogleProvider with types.WebSearchProviderParameters where params.APIKey == \"\".","commonSituations":"Config loader skipped the API key field; YAML/JSON config key typo (e.g. api_key not mapped); tenant config omits credentials; empty env var copied into params without a check.","solutions":["Populate params.APIKey with a valid Google Cloud API key enabled for Custom Search API before calling NewGoogleProvider.","Check the config mapping so the api_key field actually flows into WebSearchProviderParameters.","Add a startup validation that fails early when provider config is incomplete.","Fall back to a different configured search provider when Google parameters are absent."],"exampleFix":"// before\nprovider, err := NewGoogleProvider(types.WebSearchProviderParameters{EngineID: engineID})\n// after\nif cfg.GoogleAPIKey == \"\" {\n    return fmt.Errorf(\"google search unavailable: API key not configured\")\n}\nprovider, err := NewGoogleProvider(types.WebSearchProviderParameters{APIKey: cfg.GoogleAPIKey, EngineID: engineID})","handlingStrategy":"validation","validationCode":"if params.APIKey == \"\" {\n    return errors.New(\"google search provider requires APIKey — check config\")\n}\nprovider, err := NewGoogleProvider(params)","typeGuard":null,"tryCatchPattern":"provider, err := NewGoogleProvider(params)\nif err != nil {\n    return nil, fmt.Errorf(\"init google search provider: %w\", err)\n}","preventionTips":["Validate provider parameters at application startup, not on first request","Map config keys explicitly and fail fast on missing credentials","Keep API keys in a secret manager rather than hand-edited env files","Document required fields (APIKey, EngineID) next to provider config samples"],"tags":["configuration","google","web-search","missing-credentials"],"backgroundTag":"missing-api-key","analyzedSha":"988cbb03305e055d8ebb7d46d9ac6cc0803cd074","analyzedAt":"2026-09-02T14:41:08.344Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}