caddyserver/caddy · error
loading handshake context module: %v
Error message
loading handshake context module: %v
What it means
Returned by ConnectionPolicies.Provision when ctx.LoadModule fails to load the HandshakeContextRaw module of a connection policy (a HandshakeContext implementation that customizes the context passed to CertMagic during handshakes). This is an experimental extension point, so most users only see it when a plugin providing it fails to load.
Source
Thrown at modules/caddytls/connpolicy.go:87
err = pol.buildStandardTLSConfig(ctx)
if err != nil {
return fmt.Errorf("connection policy %d: building standard TLS config: %s", i, err)
}
if pol.ClientAuthentication != nil && len(pol.ClientAuthentication.VerifiersRaw) > 0 {
clientCertValidations, err := ctx.LoadModule(pol.ClientAuthentication, "VerifiersRaw")
if err != nil {
return fmt.Errorf("loading client cert verifiers: %v", err)
}
for _, validator := range clientCertValidations.([]any) {
cp[i].ClientAuthentication.verifiers = append(cp[i].ClientAuthentication.verifiers, validator.(ClientCertificateVerifier))
}
}
if len(pol.HandshakeContextRaw) > 0 {
modIface, err := ctx.LoadModule(pol, "HandshakeContextRaw")
if err != nil {
return fmt.Errorf("loading handshake context module: %v", err)
}
cp[i].handshakeContext = modIface.(HandshakeContext)
}
}
return nil
}
// TLSConfig returns a standard-lib-compatible TLS configuration which
// selects the first matching policy based on the ClientHello.
func (cp ConnectionPolicies) TLSConfig(ctx caddy.Context) *tls.Config {
// using ServerName to match policies is extremely common, especially in configs
// with lots and lots of different policies; we can fast-track those by indexing
// them by SNI, so we don't have to iterate potentially thousands of policies
// (TODO: this map does not account for wildcards, see if this is a problem in practice? look for reports of high connection latency with wildcard certs but low latency for non-wildcards in multi-thousand-cert deployments)
indexedBySNI := make(map[string]ConnectionPolicies)
if len(cp) > 30 {
for _, p := range cp {View on GitHub (pinned to 50e54ee279)
Solutions
- Read the wrapped error for the module ID and cause
- Verify the plugin is built in: 'caddy list-modules' should show the handshake context module
- Fix or align the plugin's configuration with its current schema
- Remove handshake_context_raw if the feature is not needed
Defensive patterns
Strategy: try-catch
Validate before calling
# If config contains handshake_context_raw, verify the module exists: caddy list-modules | grep -i handshake
Prevention
- Treat handshake context modules as experimental: test configs on a staging binary first
- Track the plugin's module ID in your config repo so renames surface during review
- Avoid API-pushing untested JSON with handshake_context_raw to production
When it happens
Trigger: JSON config sets handshake_context_raw to a module ID that is unknown (not compiled in) or whose Provision returns an error. Because the field is JSON-only, this typically comes from adapted configs or API-driven config pushes, not plain Caddyfiles.
Common situations: Running a config produced for a custom xcaddy build on a stock binary; upgrading Caddy and the plugin's module ID changed; plugin internal provisioning failure (bad plugin config).
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- loading handshake matchers: %v
- connection policy %d: building standard TLS config: %s
- loading client cert verifiers: %v
- dropping connection
- no server TLS configuration available for ClientHello: %+v
AI-assisted analysis of caddyserver/caddy@50e54ee279 (2026-08-15).
Data as JSON: /api/errors/f0299481f3a76aa3.
Report an issue: GitHub.