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

  1. Read the wrapped error for the module ID and cause
  2. Verify the plugin is built in: 'caddy list-modules' should show the handshake context module
  3. Fix or align the plugin's configuration with its current schema
  4. 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

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

Related errors


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