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

  1. Change the mode to one of exactly: request, require, verify_if_given, require_and_verify
  2. Map from nginx semantics: none->(omit), optional->request, optional_no_ca->verify_if_given, on->require_and_verify
  3. 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

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


AI-assisted analysis of caddyserver/caddy@50e54ee279 (2026-08-15). Data as JSON: /api/errors/cd5fc0b7a4aeabbd. Report an issue: GitHub.