crowdsecurity/crowdsec · error

unknown TLS client_verification value: %s

Error message

unknown TLS client_verification value: %s

What it means

TLSCfg.GetAuthType translates the client_verification string into a crypto/tls.ClientAuthType. The switch accepts NoClientCert, RequestClientCert, RequireAnyClientCert, VerifyClientCertIfGiven, and RequireAndVerifyClientCert; any other value hits the default branch and returns this error, which propagates through GetTLSConfig and aborts TLS setup.

Source

Thrown at pkg/csconfig/tls.go:45

		// sounds like a sane default: verify client cert if given, but don't make it mandatory
		return tls.VerifyClientCertIfGiven, nil
	}

	switch t.ClientVerification {
	case "NoClientCert":
		return tls.NoClientCert, nil
	case "RequestClientCert":
		log.Warn("RequestClientCert is insecure, please use VerifyClientCertIfGiven or RequireAndVerifyClientCert instead")
		return tls.RequestClientCert, nil
	case "RequireAnyClientCert":
		log.Warn("RequireAnyClientCert is insecure, please use VerifyClientCertIfGiven or RequireAndVerifyClientCert instead")
		return tls.RequireAnyClientCert, nil
	case "VerifyClientCertIfGiven":
		return tls.VerifyClientCertIfGiven, nil
	case "RequireAndVerifyClientCert":
		return tls.RequireAndVerifyClientCert, nil
	default:
		return 0, fmt.Errorf("unknown TLS client_verification value: %s", t.ClientVerification)
	}
}

func (t *TLSCfg) GetTLSConfig() (*tls.Config, error) {
	if t == nil {
		return &tls.Config{}, nil
	}

	clientAuthType, err := t.GetAuthType()
	if err != nil {
		return nil, err
	}

	caCertPool, err := x509.SystemCertPool()
	if err != nil {
		log.Warnf("Error loading system CA certificates: %s", err)
	}

View on GitHub (pinned to 909b515798)

Solutions

  1. Set client_verification to exactly one of: NoClientCert, RequestClientCert, RequireAnyClientCert, VerifyClientCertIfGiven, RequireAndVerifyClientCert.
  2. Match Go's spelling, not nginx's — replace 'required' with RequireAndVerifyClientCert and 'optional' with VerifyClientCertIfGiven.
  3. Check casing: the comparison is case-sensitive, so write the value in Go constant form (PascalCase).
  4. If you don't need client certs, simply omit client_verification or set NoClientCert.

Example fix

// before (api.server.tls in config.yaml)
tls:
  client_verification: required
// after
tls:
  client_verification: RequireAndVerifyClientCert
Defensive patterns

Strategy: validation

Validate before calling

var valid = []string{"NoClientCert", "RequestClientCert", "RequireAnyClientCert", "VerifyClientCertIfGiven", "RequireAndVerifyClientCert"}
if !slices.Contains(valid, tlsCfg.ClientVerification) {
    return fmt.Errorf("client_verification %q must be one of %v", tlsCfg.ClientVerification, valid)
}

Try / catch

if _, err := tlsCfg.GetAuthType(); err != nil {
    log.Fatalf("bad TLS config: %v", err) // correct client_verification before starting LAPI
}

Prevention

When it happens

Trigger: The tls section of the API server config sets client_verification to a value outside the five supported enum strings — typos like 'require_and_verify', 'required', or mixed case ('RequireAndVerifyclientcert' — matching is case-sensitive).

Common situations: Operators copy mTLS snippets from nginx ('optional', 'required') or other servers whose enum names differ; editing api.server.tls.client_verification by hand with a wrong casing.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


AI-assisted analysis of crowdsecurity/crowdsec@909b515798 (2026-09-06). Data as JSON: /api/errors/8f24135b9f99ee96. Report an issue: GitHub.