VictoriaMetrics/VictoriaMetrics · error

client_id cannot be empty

Error message

client_id cannot be empty

What it means

A validation guard in OAuth2Config.validate: the client_id field of the OAuth2 scrape/auth config is empty. The input at fault is the client_id yaml key under oauth2 in the configuration file being loaded.

Source

Thrown at lib/promauth/config.go:156

	Headers []string `yaml:"proxy_headers,omitempty"`
}

// OAuth2Config represent OAuth2 configuration
type OAuth2Config struct {
	ClientID         string            `yaml:"client_id"`
	ClientSecret     *Secret           `yaml:"client_secret,omitempty"`
	ClientSecretFile string            `yaml:"client_secret_file,omitempty"`
	Scopes           []string          `yaml:"scopes,omitempty"`
	TokenURL         string            `yaml:"token_url"`
	EndpointParams   map[string]string `yaml:"endpoint_params,omitempty"`
	TLSConfig        *TLSConfig        `yaml:"tls_config,omitempty"`
	ProxyURL         string            `yaml:"proxy_url,omitempty"`
	Headers          []string          `yaml:"headers,omitempty"`
}

func (o *OAuth2Config) validate() error {
	if o.ClientID == "" {
		return fmt.Errorf("client_id cannot be empty")
	}
	if o.ClientSecret == nil && o.ClientSecretFile == "" {
		return fmt.Errorf("ClientSecret or ClientSecretFile must be set")
	}
	if o.ClientSecret != nil && o.ClientSecretFile != "" {
		return fmt.Errorf("ClientSecret and ClientSecretFile cannot be set simultaneously")
	}
	if o.TokenURL == "" {
		return fmt.Errorf("token_url cannot be empty")
	}
	return nil
}

type oauth2ConfigInternal struct {
	mu               sync.Mutex
	cfg              *clientcredentials.Config
	clientSecretFile string

View on GitHub (pinned to 5079fb58f1)

Solutions

  1. Set client_id in the OAuth2 config block
  2. If using templating/env expansion, verify the variable is set in the process environment before startup
  3. Check the loaded YAML path/indentation so client_id actually lands on the OAuth2 block being validated

Example fix

// before
oauth2:
  token_url: https://idp/token
  client_secret: "s3cret"
// after
oauth2:
  token_url: https://idp/token
  client_id: "my-client"
  client_secret: "s3cret"
Defensive patterns

Strategy: validation

Validate before calling

if cfg.OAuth2 != nil && cfg.OAuth2.ClientID == "" {
    return errors.New("oauth2.client_id must be set before applying config")
}

Type guard

func oauth2ClientIDSet(o *promauth.OAuth2Config) bool {
    return o != nil && o.ClientID != ""
}

Try / catch

if err := ac.InitFromOAuth2Config(oauthCfg); err != nil {
    if strings.Contains(err.Error(), "client_id cannot be empty") {
        return fmt.Errorf("config error: oauth2 block requires client_id: %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: initFromOAuth2Config -> newOAuth2ConfigInternal -> validate() runs on an OAuth2Config whose ClientID is "" — i.e. the config's oauth2.client_id is missing or set to an empty string.

Common situations: Forgot to fill client_id in the scrape/remote-write config; environment-variable templating produced an empty value (unset env var); copy-pasted an OAuth2 block but deleted the client_id line.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


AI-assisted analysis of VictoriaMetrics/VictoriaMetrics@5079fb58f1 (2026-09-03). Data as JSON: /api/errors/af65a5cc84f84df6. Report an issue: GitHub.