juicedata/juicefs · error

error loading CA cert file: %s

Error message

error loading CA cert file: %s

What it means

After loading the client key pair, createStorage reads the CA bundle file from the `ca-certs` URL parameter with os.ReadFile. If that read fails (missing file, permission denied) the CA trust pool cannot be built, so the connection is aborted with this error.

Source

Thrown at cmd/format.go:267

			}
			object.GetHttpClient().Transport.(*http.Transport).TLSClientConfig.InsecureSkipVerify = tlsSkipVerify
			values.Del("tls-insecure-skip-verify")
			u.RawQuery = values.Encode()
			format.Bucket = u.String()
		}

		// Configure client TLS when params are provided
		if values.Get("ca-certs") != "" && values.Get("ssl-cert") != "" && values.Get("ssl-key") != "" {

			clientTLSCert, err := tls.LoadX509KeyPair(values.Get("ssl-cert"), values.Get("ssl-key"))
			if err != nil {
				return nil, fmt.Errorf("error loading certificate and key file: %s", err.Error())
			}

			certPool := x509.NewCertPool()
			caCertPEM, err := os.ReadFile(values.Get("ca-certs"))
			if err != nil {
				return nil, fmt.Errorf("error loading CA cert file: %s", err.Error())
			}

			if certAdded := certPool.AppendCertsFromPEM(caCertPEM); !certAdded {
				return nil, fmt.Errorf("error appending CA cert to pool")
			}

			object.GetHttpClient().Transport.(*http.Transport).TLSClientConfig.RootCAs = certPool
			object.GetHttpClient().Transport.(*http.Transport).TLSClientConfig.Certificates = []tls.Certificate{clientTLSCert}
		}
	}

	if format.Shards > 1 {
		blob, err = object.NewSharded(strings.ToLower(format.Storage), format.Bucket, format.AccessKey, format.SecretKey, format.SessionToken, format.Shards)
	} else {
		blob, err = object.CreateStorage(strings.ToLower(format.Storage), format.Bucket, format.AccessKey, format.SecretKey, format.SessionToken)
	}
	if err != nil {
		return nil, err

View on GitHub (pinned to c9a67b23e8)

Solutions

  1. Check the ca-certs path exists and is readable (ls/os.stat) from the process working directory.
  2. Use an absolute path for ca-certs in the storage URL.
  3. Mount the CA file into the container/pod and fix permissions if running containerized.
  4. Remove the ca-certs param if you intend to use the system CA pool instead.

Example fix

// before
s3://bucket?ca-certs=ca.pem&ssl-cert=c.pem&ssl-key=k.pem   # ca.pem not in cwd
// after
s3://bucket?ca-certs=/etc/juicefs/ca.pem&ssl-cert=/etc/juicefs/c.pem&ssl-key=/etc/juicefs/k.pem
Defensive patterns

Strategy: validation

Validate before calling

if _, err := os.Stat(caPath); err != nil {
	return fmt.Errorf("CA bundle unreadable before mount: %w", err)
}

Try / catch

caCertPEM, err := os.ReadFile(caPath)
if err != nil {
	return nil, fmt.Errorf("error loading CA cert file: %s", err.Error())
}

Prevention

When it happens

Trigger: Storage URL includes `ca-certs=<path>` (together with ssl-cert/ssl-key) and the CA file cannot be read: nonexistent path, wrong relative path, or unreadable permissions.

Common situations: Mount run inside a container without the CA file mounted; path relative to a different working directory than the daemon's; CA bundle regenerated/renamed after the volume was formatted.

Understand the failure class

Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.

Related errors


AI-assisted analysis of juicedata/juicefs@c9a67b23e8 (2026-09-06). Data as JSON: /api/errors/4e6b0588bad45db7. Report an issue: GitHub.