googleapis/mcp-toolbox · error
client id or client secret not valid
Error message
client id or client secret not valid
What it means
GetLookerSDK returns the configured Looker SDK client, but if the Source's LookerClient was never initialized (because client id/secret credentials were missing or invalid during Initialize), it fails with this message. It guards against returning a nil SDK that would panic downstream. The check `s.LookerClient() == nil` means the API3 credentials supplied to Looker did not yield a usable client.
Source
Thrown at internal/sources/looker/looker.go:278
TLSClientConfig: &tls.Config{
InsecureSkipVerify: !s.LookerApiSettings().VerifySsl,
},
}
// Build transport for end user token
session.Client = http.Client{
Transport: &transportWithAuthHeader{
Base: transport,
AuthToken: accessToken,
clientIP: clientIP,
},
}
// return SDK with new Transport
return v4.NewLookerSDK(session), nil
}
if s.LookerClient() == nil {
return nil, fmt.Errorf("client id or client secret not valid")
}
return s.LookerClient(), nil
}
func initGoogleCloudConnection(ctx context.Context) (oauth2.TokenSource, error) {
cred, err := google.FindDefaultCredentials(ctx, geminidataanalytics.DefaultAuthScopes()...)
if err != nil {
return nil, fmt.Errorf("failed to find default Google Cloud credentials with scope %q: %w", geminidataanalytics.DefaultAuthScopes(), err)
}
return cred.TokenSource, nil
}
func (s *Source) GetHostURL(ctx context.Context, sdk *v4.LookerSDK) (string, error) {
defaultURL := strings.TrimSuffix(s.ApiSettings.BaseUrl, "/")
if sdk == nil {
return defaultURL, nilView on GitHub (pinned to 8cc6e09de2)
Solutions
- Set valid client_id and client_secret (Looker API3 credentials) in the source config or environment and re-initialize the toolbox
- Generate new API3 credentials in Looker under Admin > Users > API keys and use those values
- Verify the credentials are enabled and belong to an active Looker user with required permissions
Example fix
// before
s.LookerClient() == nil // "client id or client secret not valid"
// after
// config yaml:
// client_id: ${LOOKER_CLIENT_ID}
// client_secret: ${LOOKER_CLIENT_SECRET}
export LOOKER_CLIENT_ID=abc123
export LOOKER_CLIENT_SECRET=xyz789 Defensive patterns
Strategy: validation
Validate before calling
if os.Getenv("LOOKER_CLIENT_ID") == "" || os.Getenv("LOOKER_CLIENT_SECRET") == "" {
return fmt.Errorf("LOOKER_CLIENT_ID and LOOKER_CLIENT_SECRET must be set")
} Type guard
if client := src.LookerClient(); client == nil {
return fmt.Errorf("looker client not initialized; check client id/secret")
} Try / catch
sdk, err := src.GetLookerSDK(ctx)
if err != nil {
if strings.Contains(err.Error(), "client id or client secret not valid") {
// re-load credentials and re-initialize source
}
return err
} Prevention
- Load client id/secret from a secret manager instead of ad-hoc env vars
- Validate credentials by calling a cheap Looker API (e.g. /versions) at startup
- Rotate API3 keys before they are disabled in Looker
When it happens
Trigger: Calling GetLookerSDK on a Source whose client id or client secret was empty/invalid at Initialize time, so the lookersdk session was never built and LookerClient() returns nil.
Common situations: Environment variables or YAML config missing client_id/client_secret; credentials typed incorrectly; using API credentials that were disabled or deleted in the Looker admin console.
Related errors
- client_id and client_secret need to be specified
- failed to find default Google Cloud credentials with scope %
- failed to find default Google Cloud credentials with scope %
- elasticsearch source %q requires either username/password or
- unable to parse Timeout string as time.Duration: %s
AI-assisted analysis of googleapis/mcp-toolbox@8cc6e09de2 (2026-09-05).
Data as JSON: /api/errors/505f2b6c3e43ce46.
Report an issue: GitHub.