crowdsecurity/crowdsec · error

failed to load cacert: %w

Error message

failed to load cacert: %w

What it means

When the credentials configuration specifies a ca_cert_path, Load() reads that file with os.ReadFile to build the TLS CA pool. This error wraps the read failure, meaning the CA certificate file could not be loaded — most often because the path does not exist or is unreadable. It is thrown before any TLS handshake happens.

Source

Thrown at pkg/csconfig/api.go:199

	if credTLS && credSocket {
		return errors.New("cannot use TLS with a unix socket")
	}

	if credTLSClientAuth && l.Credentials.Login != "" {
		return errors.New("user/password authentication and TLS authentication are mutually exclusive")
	}

	if l.InsecureSkipVerify == nil {
		apiclient.InsecureSkipVerify = false
	} else {
		apiclient.InsecureSkipVerify = *l.InsecureSkipVerify
	}

	if l.Credentials.CACertPath != "" {
		caCert, err := os.ReadFile(l.Credentials.CACertPath)
		if err != nil {
			return fmt.Errorf("failed to load cacert: %w", err)
		}

		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 {

View on GitHub (pinned to 909b515798)

Solutions

  1. Check the path in the error's wrapped message with `ls -l <path>`; fix the ca_cert_path value to point at the real CA file.
  2. Re-copy the CA certificate from the LAPI host (`/etc/crowdsec/ssl/ca.crt` by default) to the client.
  3. Fix file permissions so the crowdsec user can read the cert (e.g. chmod 644).
  4. Use an absolute path, since relative paths resolve against the daemon's working directory.
  5. If TLS verification is intentionally not needed, remove ca_cert_path or set insecure_skip_verify (dev only).

Example fix

# before
ca_cert_path: /etc/crowdsec/ssl/ca.cr  # wrong name
# after
ca_cert_path: /etc/crowdsec/ssl/ca.crt
Defensive patterns

Strategy: validation

Validate before calling

if caPath != "" {
    if _, err := os.Stat(caPath); err != nil {
        return fmt.Errorf("CA cert not readable at %s: %w", caPath, err)
    }
}

Try / catch

if err := creds.Load(); err != nil {
    var perr *fs.PathError
    if errors.As(err, &perr) && strings.Contains(err.Error(), "failed to load cacert") {
        return fmt.Errorf("CA cert %s missing/unreadable: %w", perr.Path, err)
    }
    return err
}

Prevention

When it happens

Trigger: Credentials.CACertPath is set in the api client config and os.ReadFile fails: nonexistent path, permission denied, path is a directory, or the file was deleted/moved after config was written.

Common situations: Wrong relative path in local_api_credentials.yaml (paths resolve relative to process CWD, not the config file); CA cert regenerated on LAPI but client still points at the old file; container image missing the mounted cert; typo like /etc/ssl/certs/ca-cert.cr instead of .crt.

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.

Related errors


AI-assisted analysis of crowdsecurity/crowdsec@909b515798 (2026-09-06). Data as JSON: /api/errors/04a76cd23b791903. Report an issue: GitHub.