{"record":{"id":"d7ac7e62c0d7655b","repo":"crowdsecurity/crowdsec","slug":"failed-to-load-api-client-certificate-w","errorCode":null,"errorMessage":"failed to load api client certificate: %w","messagePattern":"failed to load api client certificate: %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/csconfig/api.go","lineNumber":218,"sourceCode":"\t\t}\n\n\t\tcaCertPool, err := x509.SystemCertPool()\n\t\tif err != nil {\n\t\t\tlog.Warningf(\"Error loading system CA certificates: %s\", err)\n\t\t}\n\n\t\tif caCertPool == nil {\n\t\t\tcaCertPool = x509.NewCertPool()\n\t\t}\n\n\t\tcaCertPool.AppendCertsFromPEM(caCert)\n\t\tapiclient.CaCertPool = caCertPool\n\t}\n\n\tif l.Credentials.CertPath != \"\" && l.Credentials.KeyPath != \"\" {\n\t\tcert, err := tls.LoadX509KeyPair(l.Credentials.CertPath, l.Credentials.KeyPath)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"failed to load api client certificate: %w\", err)\n\t\t}\n\n\t\tapiclient.Cert = &cert\n\t}\n\n\treturn nil\n}\n\n// local api service configuration\ntype LocalApiServerCfg struct {\n\tEnable                        *bool                    `yaml:\"enable\"`\n\tListenURI                     string                   `yaml:\"listen_uri,omitempty\"` // 127.0.0.1:8080\n\tListenSocket                  string                   `yaml:\"listen_socket,omitempty\"`\n\tTLS                           *TLSCfg                  `yaml:\"tls\"`\n\tDbConfig                      *DatabaseCfg             `yaml:\"-\"`\n\tOnlineClient                  *OnlineApiClientCfg      `yaml:\"online_client\"`\n\tProfilesPath                  string                   `yaml:\"profiles_path,omitempty\"`\n\tConsoleConfigPath             string                   `yaml:\"console_path,omitempty\"`","sourceCodeStart":200,"sourceCodeEnd":236,"githubUrl":"https://github.com/crowdsecurity/crowdsec/blob/909b5157986a2b2c2163300fdaef5ed01289f7d2/pkg/csconfig/api.go#L200-L236","documentation":"When both cert_path and key_path are configured, Load() calls tls.LoadX509KeyPair to load the client mTLS pair. This error wraps any failure from the Go TLS package: unreadable files, malformed PEM data, or a certificate/key mismatch. It is thrown during config load, before the API client dials the server.","triggerScenarios":"Credentials.CertPath and Credentials.KeyPath are both set and tls.LoadX509KeyPair fails: missing or unreadable file, invalid PEM blocks, key encrypted with a passphrase, or cert/key derived from different CSRs.","commonSituations":"Client cert and key from different enrollments copied into the config; cert file containing only the CA cert rather than the client cert; key regenerated after the certificate was issued; SELinux or mount permissions blocking the key file; files pasted without the BEGIN/END lines.","solutions":["Verify both files exist and are readable: `ls -l <cert> <key>` and `openssl x509 -in cert.pem -noout` / `openssl rsa -in key.pem -check`.","Confirm the cert and key match: compare `openssl x509 -noout -modulus` and `openssl rsa -noout -modulus` outputs.","Regenerate the client pair on the LAPI host (`cscli users add`/`cscli lapi register` flow) and redeploy both files together.","Fix permissions on the key file (often 600 and owned by the service user).","If mTLS is not required, remove cert_path/key_path from the credentials config."],"exampleFix":"// before: mismatched pair\ncert_path: /etc/crowdsec/ssl/client-old.crt\nkey_path: /etc/crowdsec/ssl/client-new.key\n// after: matching regenerated pair\ncert_path: /etc/crowdsec/ssl/client.crt\nkey_path: /etc/crowdsec/ssl/client.key","handlingStrategy":"validation","validationCode":"if certPath != \"\" && keyPath != \"\" {\n    if _, err := tls.LoadX509KeyPair(certPath, keyPath); err != nil {\n        return fmt.Errorf(\"client mTLS pair invalid: %w\", err)\n    }\n}","typeGuard":null,"tryCatchPattern":"if err := creds.Load(); err != nil {\n    if strings.Contains(err.Error(), \"failed to load api client certificate\") {\n        return fmt.Errorf(\"mTLS pair invalid, regenerate with 'cscli lapi register': %w\", err)\n    }\n    return err\n}","preventionTips":["Always deploy cert and key together as an atomic pair.","Validate with `openssl x509 -noout -modulus` vs `openssl rsa -noout -modulus` before rollout.","Ensure the key file is unencrypted (no passphrase) for unattended services.","Check PEM blocks are intact after transfer (no truncation or base64 wrapping)."],"tags":["tls","mtls","config"],"backgroundTag":"file-read-failed","analyzedSha":"909b5157986a2b2c2163300fdaef5ed01289f7d2","analyzedAt":"2026-09-06T12:27:26.012Z","contentChangedAt":"2026-09-06T12:27:26.012Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}