crowdsecurity/crowdsec · error
failed to load api client certificate: %w
Error message
failed to load api client certificate: %w
What it means
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.
Source
Thrown at pkg/csconfig/api.go:218
}
caCertPool, err := x509.SystemCertPool()
if err != nil {
log.Warningf("Error loading system CA certificates: %s", err)
}
if caCertPool == nil {
caCertPool = x509.NewCertPool()
}
caCertPool.AppendCertsFromPEM(caCert)
apiclient.CaCertPool = caCertPool
}
if l.Credentials.CertPath != "" && l.Credentials.KeyPath != "" {
cert, err := tls.LoadX509KeyPair(l.Credentials.CertPath, l.Credentials.KeyPath)
if err != nil {
return fmt.Errorf("failed to load api client certificate: %w", err)
}
apiclient.Cert = &cert
}
return nil
}
// local api service configuration
type LocalApiServerCfg struct {
Enable *bool `yaml:"enable"`
ListenURI string `yaml:"listen_uri,omitempty"` // 127.0.0.1:8080
ListenSocket string `yaml:"listen_socket,omitempty"`
TLS *TLSCfg `yaml:"tls"`
DbConfig *DatabaseCfg `yaml:"-"`
OnlineClient *OnlineApiClientCfg `yaml:"online_client"`
ProfilesPath string `yaml:"profiles_path,omitempty"`
ConsoleConfigPath string `yaml:"console_path,omitempty"`View on GitHub (pinned to 909b515798)
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.
Example fix
// before: mismatched pair cert_path: /etc/crowdsec/ssl/client-old.crt key_path: /etc/crowdsec/ssl/client-new.key // after: matching regenerated pair cert_path: /etc/crowdsec/ssl/client.crt key_path: /etc/crowdsec/ssl/client.key
Defensive patterns
Strategy: validation
Validate before calling
if certPath != "" && keyPath != "" {
if _, err := tls.LoadX509KeyPair(certPath, keyPath); err != nil {
return fmt.Errorf("client mTLS pair invalid: %w", err)
}
} Try / catch
if err := creds.Load(); err != nil {
if strings.Contains(err.Error(), "failed to load api client certificate") {
return fmt.Errorf("mTLS pair invalid, regenerate with 'cscli lapi register': %w", err)
}
return err
} Prevention
- 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).
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- machine %s attempted to auth with TLS cert but it is configu
- unknown TLS client_verification value: %s
- tls authentication required
- certificate revoked by OCSP
- certificate revoked by CRL
AI-assisted analysis of crowdsecurity/crowdsec@909b515798 (2026-09-06).
Data as JSON: /api/errors/d7ac7e62c0d7655b.
Report an issue: GitHub.