caddyserver/caddy · error
client auth mode not recognized: %s
Error message
client auth mode not recognized: %s
What it means
ClientAuthentication.Configure sets the Go TLS ClientAuth mode from clientauth.Mode; only four strings are accepted: request, require, verify_if_given, require_and_verify. Anything else fails handshake configuration. If Mode is empty a safe default is derived from whether trust material (CA certs, verifiers, or a CA module) is present.
Source
Thrown at modules/caddytls/connpolicy.go:853
// if there's no actionable client auth, simply disable it
if !clientauth.Active() {
cfg.ClientAuth = tls.NoClientCert
return nil
}
// enforce desired mode of client authentication
if len(clientauth.Mode) > 0 {
switch clientauth.Mode {
case "request":
cfg.ClientAuth = tls.RequestClientCert
case "require":
cfg.ClientAuth = tls.RequireAnyClientCert
case "verify_if_given":
cfg.ClientAuth = tls.VerifyClientCertIfGiven
case "require_and_verify":
cfg.ClientAuth = tls.RequireAndVerifyClientCert
default:
return fmt.Errorf("client auth mode not recognized: %s", clientauth.Mode)
}
} else {
// otherwise, set a safe default mode
if len(clientauth.TrustedCACerts) > 0 ||
len(clientauth.TrustedCACertPEMFiles) > 0 ||
len(clientauth.TrustedLeafCerts) > 0 ||
clientauth.CARaw != nil || clientauth.ca != nil {
cfg.ClientAuth = tls.RequireAndVerifyClientCert
} else {
cfg.ClientAuth = tls.RequireAnyClientCert
}
}
// enforce CA verification by adding CA certs to the ClientCAs pool
if clientauth.ca != nil {
cfg.ClientCAs = clientauth.ca.CertPool()
}
View on GitHub (pinned to 50e54ee279)
Solutions
- Change the mode to one of exactly: request, require, verify_if_given, require_and_verify
- Map from nginx semantics: none->(omit), optional->request, optional_no_ca->verify_if_given, on->require_and_verify
- Run caddy validate --config <file> to catch it before restart
Example fix
# before
client_auth {
mode optional
}
# after
client_auth {
mode verify_if_given
} Defensive patterns
Strategy: validation
Validate before calling
var validClientAuthModes = map[string]bool{
"request": true, "require": true,
"verify_if_given": true, "require_and_verify": true,
}
func validateMode(mode string) error {
if !validClientAuthModes[mode] {
return fmt.Errorf("invalid client auth mode %q; want one of request, require, verify_if_given, require_and_verify", mode)
}
return nil
} Type guard
func isValidClientAuthMode(mode string) bool {
switch mode {
case "request", "require", "verify_if_given", "require_and_verify":
return true
}
return false
} Prevention
- Keep a fleet-wide mapping from nginx ssl_verify_client values to Caddy modes
- Template client_auth blocks from one tested snippet instead of hand-typing modes
- Validate configs in CI: caddy validate --adapter caddyfile --config Caddyfile
When it happens
Trigger: Typing an invalid mode string into client_auth { mode ... } in a Caddyfile or the "mode" JSON field, e.g. 'require_verify', 'optional', 'verify', 'none', or a quoted JSON value with different casing like 'Require'.
Common situations: Migrating from nginx ('ssl_verify_client optional' has no 1:1 name here — the equivalent is verify_if_given) or from old Caddy versions/docs; autocomplete or memory producing plausible-but-wrong mode names.
Related errors
- client_certificate_file specified without client_certificate
- client_certificate_key_file specified without client_certifi
- conflicting config for client authentication trust CA
- could not parse leaf certificates loaders: %s
- automation policy %d is the second policy that acts as defau
AI-assisted analysis of caddyserver/caddy@50e54ee279 (2026-08-15).
Data as JSON: /api/errors/cd5fc0b7a4aeabbd.
Report an issue: GitHub.