{"record":{"id":"663fd4286aaf55ca","repo":"kubernetes/kops","slug":"error-reading-client-keypair-v","errorCode":null,"errorMessage":"error reading client keypair: %v","messagePattern":"error reading client keypair: (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"cmd/kube-apiserver-healthcheck/main.go","lineNumber":166,"sourceCode":"\n\tflag.Parse()\n\n\ttlsConfig := &tls.Config{}\n\n\tif caCert != \"\" {\n\t\tb, err := os.ReadFile(caCert)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"error reading certificate %q: %v\", caCert, err)\n\t\t}\n\t\trootCAs := x509.NewCertPool()\n\t\trootCAs.AppendCertsFromPEM(b)\n\t\ttlsConfig.RootCAs = rootCAs\n\t}\n\n\tif clientKey != \"\" {\n\t\tkeypair, err := tls.LoadX509KeyPair(clientCert, clientKey)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"error reading client keypair: %v\", err)\n\t\t}\n\n\t\ttlsConfig.Certificates = []tls.Certificate{keypair}\n\t}\n\n\ttransport := &http.Transport{\n\t\tTLSClientConfig: tlsConfig,\n\t}\n\n\ts := &healthCheckServer{\n\t\ttransport: transport,\n\t}\n\n\thttp.HandleFunc(\"/\", s.handler)\n\n\tklog.Infof(\"listening on %s\", listen)\n\n\tif err := http.ListenAndServe(listen, nil); err != nil {","sourceCodeStart":148,"sourceCodeEnd":184,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/cmd/kube-apiserver-healthcheck/main.go#L148-L184","documentation":"Thrown in run() when tls.LoadX509KeyPair fails to load or parse the client certificate/key pair configured via --client-cert and --client-key. Either file is missing/unreadable or the pair is malformed or mismatched, so mTLS authentication to the API server cannot be set up.","triggerScenarios":"--client-key set but the cert/key files don't exist or are unreadable; cert and key don't match; files are not valid PEM; key is an unsupported format/encryption.","commonSituations":"Secrets mounted as separate volumes with one path wrong; expired/rotated certificate with mismatched key; PEM blocks corrupted by secret encoding; typo swapping cert and key flags.","solutions":["Verify both files exist, are readable, and are valid PEM (openssl x509 / openssl rsa on each).","Confirm cert and key are a matching pair (compare modulus/public key hashes).","Fix the --client-cert/--client-key paths or re-mount the correct secret.","Regenerate the client keypair if rotated or mismatched, then restart the healthcheck."],"exampleFix":"// before (paths swapped)\nrun(\"--client-cert\", \"/pki/client.key\", \"--client-key\", \"/pki/client.crt\")\n// after\nrun(\"--client-cert\", \"/pki/client.crt\", \"--client-key\", \"/pki/client.key\")","handlingStrategy":"validation","validationCode":"// preflight: load the pair before handing paths to the server\nif _, err := tls.LoadX509KeyPair(clientCertPath, clientKeyPath); err != nil {\n    return fmt.Errorf(\"client keypair preflight failed: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"// Go: fail fast with context at startup\nif err := run(); err != nil {\n    if strings.Contains(err.Error(), \"client keypair\") {\n        klog.Fatalf(\"TLS client config invalid: %v\", err)\n    }\n    klog.Fatalf(\"healthcheck terminated: %v\", err)\n}","preventionTips":["Generate cert/key together and rotate them as a pair.","Verify pairs with `openssl x509 -noout -modulus` vs `openssl rsa -noout -modulus`.","Double-check --client-cert and --client-key are not swapped.","Keep PEM files base64-decoded correctly when templating from secrets."],"tags":["tls","mtls","certificates","keypair"],"backgroundTag":"tls-keypair-load-failed","analyzedSha":"4c8573c808a73d578c5eadc86d410646ea0b0d73","analyzedAt":"2026-09-05T04:13:19.212Z","contentChangedAt":"2026-09-05T04:13:19.212Z","schemaVersion":2},"datasetVersion":"2026-09-12T12:17:11.808Z"}