{"record":{"id":"f0299481f3a76aa3","repo":"caddyserver/caddy","slug":"loading-handshake-context-module-v","errorCode":null,"errorMessage":"loading handshake context module: %v","messagePattern":"loading handshake context module: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"modules/caddytls/connpolicy.go","lineNumber":87,"sourceCode":"\t\terr = pol.buildStandardTLSConfig(ctx)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"connection policy %d: building standard TLS config: %s\", i, err)\n\t\t}\n\n\t\tif pol.ClientAuthentication != nil && len(pol.ClientAuthentication.VerifiersRaw) > 0 {\n\t\t\tclientCertValidations, err := ctx.LoadModule(pol.ClientAuthentication, \"VerifiersRaw\")\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"loading client cert verifiers: %v\", err)\n\t\t\t}\n\t\t\tfor _, validator := range clientCertValidations.([]any) {\n\t\t\t\tcp[i].ClientAuthentication.verifiers = append(cp[i].ClientAuthentication.verifiers, validator.(ClientCertificateVerifier))\n\t\t\t}\n\t\t}\n\n\t\tif len(pol.HandshakeContextRaw) > 0 {\n\t\t\tmodIface, err := ctx.LoadModule(pol, \"HandshakeContextRaw\")\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"loading handshake context module: %v\", err)\n\t\t\t}\n\t\t\tcp[i].handshakeContext = modIface.(HandshakeContext)\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// TLSConfig returns a standard-lib-compatible TLS configuration which\n// selects the first matching policy based on the ClientHello.\nfunc (cp ConnectionPolicies) TLSConfig(ctx caddy.Context) *tls.Config {\n\t// using ServerName to match policies is extremely common, especially in configs\n\t// with lots and lots of different policies; we can fast-track those by indexing\n\t// them by SNI, so we don't have to iterate potentially thousands of policies\n\t// (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)\n\tindexedBySNI := make(map[string]ConnectionPolicies)\n\tif len(cp) > 30 {\n\t\tfor _, p := range cp {","sourceCodeStart":69,"sourceCodeEnd":105,"githubUrl":"https://github.com/caddyserver/caddy/blob/50e54ee279aa1e504fe218ca49ab6ae16c100410/modules/caddytls/connpolicy.go#L69-L105","documentation":"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.","triggerScenarios":"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.","commonSituations":"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).","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"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"# If config contains handshake_context_raw, verify the module exists:\ncaddy list-modules | grep -i handshake","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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"],"tags":["caddy","tls","modules","connection-policy","experimental"],"backgroundTag":null,"analyzedSha":"50e54ee279aa1e504fe218ca49ab6ae16c100410","analyzedAt":"2026-08-15T09:20:21.641Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}