istio/istio · error

private key provider configuration is required

Error message

private key provider configuration is required

What it means

Thrown by validatePrivateKeyProvider (reached from ValidateMeshConfigProxyConfig, which prefixes it with 'invalid private key provider configuration:') when a PrivateKeyProvider message is present but its oneof provider field is nil. The PrivateKeyProvider proto requires exactly one concrete provider (cryptomb or qat); an empty message means the hardware private-key provider for the proxy cannot be constructed.

Source

Thrown at pkg/config/validation/agent/validation.go:471

		if err := validateConnectionSettings(cs); err != nil {
			errs = multierror.Append(errs, multierror.Prefix(err, "invalid connection settings:"))
		}
	}

	return Validation{errs, warnings}
}

func ValidateControlPlaneAuthPolicy(policy meshconfig.AuthenticationPolicy) error {
	if policy == meshconfig.AuthenticationPolicy_NONE || policy == meshconfig.AuthenticationPolicy_MUTUAL_TLS {
		return nil
	}
	return fmt.Errorf("unrecognized control plane auth policy %q", policy)
}

func validatePrivateKeyProvider(pkpConf *meshconfig.PrivateKeyProvider) error {
	var errs error
	if pkpConf.GetProvider() == nil {
		errs = multierror.Append(errs, errors.New("private key provider configuration is required"))
	}

	switch pkpConf.GetProvider().(type) {
	case *meshconfig.PrivateKeyProvider_Cryptomb:
		cryptomb := pkpConf.GetCryptomb()
		if cryptomb == nil {
			errs = multierror.Append(errs, errors.New("cryptomb configuration is required"))
		} else {
			pollDelay := cryptomb.GetPollDelay()
			if pollDelay == nil {
				errs = multierror.Append(errs, errors.New("pollDelay is required"))
			} else if pollDelay.GetSeconds() == 0 && pollDelay.GetNanos() == 0 {
				errs = multierror.Append(errs, errors.New("pollDelay must be non zero"))
			}
		}
	case *meshconfig.PrivateKeyProvider_Qat:
		qatConf := pkpConf.GetQat()
		if qatConf == nil {

View on GitHub (pinned to 8dc789c5cf)

Solutions

  1. Set the provider oneof: add either `cryptomb: {pollDelay: ...}` or `qat: {pollDelay: ...}` under privateKeyProvider.
  2. If you do not need a hardware private key provider, delete the privateKeyProvider stanza entirely — validation only runs when the field is non-nil.
  3. Check YAML indentation: a mis-indented cryptomb/qat block parses as nothing, leaving the parent message empty.
  4. Re-run istioctl validate to confirm the prefixed error disappears.

Example fix

# before
defaultConfig:
  privateKeyProvider: {}

# after
defaultConfig:
  privateKeyProvider:
    cryptomb:
      pollDelay: 5s
Defensive patterns

Strategy: validation

Validate before calling

func checkPrivateKeyProvider(pc *meshconfig.ProxyConfig) error {
	pkp := pc.GetPrivateKeyProvider()
	if pkp == nil {
		return nil // field optional
	}
	if pkp.GetProvider() == nil {
		return fmt.Errorf("privateKeyProvider present but no cryptomb/qat case set")
	}
	return nil
}

Type guard

func hasPrivateKeyProviderCase(pkp *meshconfig.PrivateKeyProvider) bool {
	switch pkp.GetProvider().(type) {
	case *meshconfig.PrivateKeyProvider_Cryptomb, *meshconfig.PrivateKeyProvider_Qat:
		return true
	}
	return false
}

Prevention

When it happens

Trigger: meshConfig.defaultConfig.privateKeyProvider is set to an empty object — e.g. `privateKeyProvider: {}` in mesh.yaml, or a Go struct &meshconfig.PrivateKeyProvider{} with no provider case — and ValidateMeshConfig/ValidateMeshConfigProxyConfig runs on it.

Common situations: YAML that declares the key but leaves it empty (intent to 'enable it later'); Helm overlays merging to an empty object; protobuf unmarshalling of a partial JSON/YAML config where the oneof was never populated.

Related errors


AI-assisted analysis of istio/istio@8dc789c5cf (2026-08-15). Data as JSON: /api/errors/5a3134fda1eaabb9. Report an issue: GitHub.