{"record":{"id":"32089e273d75144c","repo":"caddyserver/caddy","slug":"client-certificate-key-file-specified-without-clie","errorCode":null,"errorMessage":"client_certificate_key_file specified without client_certificate_file","messagePattern":"client_certificate_key_file specified without client_certificate_file","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"modules/caddyhttp/reverseproxy/httptransport.go","lineNumber":798,"sourceCode":"\t// The value can be a list of any valid tcp port numbers, default empty.\n\tExceptPorts []string `json:\"except_ports,omitempty\"`\n\n\t// The list of elliptic curves to support. Caddy's\n\t// defaults are modern and secure.\n\tCurves []string `json:\"curves,omitempty\"`\n}\n\n// MakeTLSClientConfig returns a tls.Config usable by a client to a backend.\n// If there is no custom TLS configuration, a nil config may be returned.\nfunc (t *TLSConfig) MakeTLSClientConfig(ctx caddy.Context) (*tls.Config, error) {\n\tcfg := new(tls.Config)\n\n\t// client auth\n\tif t.ClientCertificateFile != \"\" && t.ClientCertificateKeyFile == \"\" {\n\t\treturn nil, fmt.Errorf(\"client_certificate_file specified without client_certificate_key_file\")\n\t}\n\tif t.ClientCertificateFile == \"\" && t.ClientCertificateKeyFile != \"\" {\n\t\treturn nil, fmt.Errorf(\"client_certificate_key_file specified without client_certificate_file\")\n\t}\n\tif t.ClientCertificateFile != \"\" && t.ClientCertificateKeyFile != \"\" {\n\t\tcert, err := tls.LoadX509KeyPair(t.ClientCertificateFile, t.ClientCertificateKeyFile)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"loading client certificate key pair: %v\", err)\n\t\t}\n\t\tcfg.Certificates = []tls.Certificate{cert}\n\t}\n\tif t.ClientCertificateAutomate != \"\" {\n\t\t// TODO: use or enable ctx.IdentityCredentials() ...\n\t\ttlsAppIface, err := ctx.App(\"tls\")\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"getting tls app: %v\", err)\n\t\t}\n\t\ttlsApp := tlsAppIface.(*caddytls.TLS)\n\t\terr = tlsApp.Manage(map[string]struct{}{t.ClientCertificateAutomate: {}})\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"managing client certificate: %v\", err)","sourceCodeStart":780,"sourceCodeEnd":816,"githubUrl":"https://github.com/caddyserver/caddy/blob/50e54ee279aa1e504fe218ca49ab6ae16c100410/modules/caddyhttp/reverseproxy/httptransport.go#L780-L816","documentation":"Mirror of the pairing check for mTLS: a private key file was supplied via client_certificate_key_file but client_certificate_file is empty. Since a key alone cannot authenticate the client, MakeTLSClientConfig rejects the combination during provisioning before any connection is attempted.","triggerScenarios":"transport http { tls { client_certificate_key_file /etc/certs/client.key } } with the certificate line missing; JSON with only \"client_certificate_key_file\" populated.","commonSituations":"Swapped or half-edited config after splitting a combined PEM into cert/key files; templating that emits the key but silently drops the cert line; leftover key directive after switching to client_certificate_automate without deleting the old line.","solutions":["Add the corresponding client_certificate_file directive with the client certificate PEM.","Run caddy validate --config to catch the pairing error before touching the running instance.","If migrating to automated certificates, delete the key file directive entirely rather than leaving it set."],"exampleFix":"// before (Caddyfile)\ntransport http {\n    tls {\n        client_certificate_key_file /etc/certs/client.key\n    }\n}\n\n// after\ntransport http {\n    tls {\n        client_certificate_file /etc/certs/client.pem\n        client_certificate_key_file /etc/certs/client.key\n    }\n}","handlingStrategy":"validation","validationCode":"func validateClientCertPair(certFile, keyFile string) error {\n    if certFile == \"\" && keyFile != \"\" {\n        return fmt.Errorf(\"client_certificate_key_file specified without client_certificate_file\")\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never leave a lone key directive when editing mTLS blocks.","Delete both fields together when switching to client_certificate_automate.","Validate configs in CI."],"tags":["config","mtls","tls","reverseproxy","validation"],"backgroundTag":null,"analyzedSha":"50e54ee279aa1e504fe218ca49ab6ae16c100410","analyzedAt":"2026-08-15T09:20:21.641Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}