docker/cli · error · invalidParameterErr
unable to get system cert pool
Error message
unable to get system cert pool: %w
What it means
Returned by loadTLSConfig in docker-trust's registry package (registry.go:53) when x509.SystemCertPool() fails while initializing RootCAs for a .crt certificate being loaded. On Linux SystemCertPool reads the system bundle; failure usually means the bundle path is unreadable or the OS provides none. The error is wrapped via invalidParam.
Solutions
- Install the system CA bundle: `apt-get install ca-certificates` / `apk add ca-certificates`.
- Ensure the bundle at /etc/ssl/certs/ca-certificates.crt (or SSL_CERT_FILE) is readable and valid PEM.
- Pre-populate tlsConfig.RootCAs yourself before calling ReadCertsDirectory so the SystemCertPool path is skipped.
- Set SSL_CERT_FILE/SSL_CERT_DIR to a known-good bundle.
Example fix
// before
tlsConfig := &tls.Config{}
if err := registry.ReadCertsDirectory(tlsConfig, certDir); err != nil { ... }
// after: seed RootCAs so SystemCertPool() is never called
pool := x509.NewCertPool()
if b, err := os.ReadFile("/etc/ssl/certs/ca-certificates.crt"); err == nil {
pool.AppendCertsFromPEM(b)
}
tlsConfig.RootCAs = pool
err := registry.ReadCertsDirectory(tlsConfig, certDir) Defensive patterns
Strategy: validation
Validate before calling
// Seed RootCAs so SystemCertPool() is never called by ReadCertsDirectory
pool := x509.NewCertPool()
if b, err := os.ReadFile(os.Getenv("SSL_CERT_FILE")); err == nil {
pool.AppendCertsFromPEM(b)
} else if b, err := os.ReadFile("/etc/ssl/certs/ca-certificates.crt"); err == nil {
pool.AppendCertsFromPEM(b)
}
tlsConfig.RootCAs = pool Try / catch
// Fallback: if SystemCertPool fails, build a fresh pool
if _, err := x509.SystemCertPool(); err != nil {
tlsConfig.RootCAs = x509.NewCertPool()
} Prevention
- Install ca-certificates in minimal images.
- Set SSL_CERT_FILE/SSL_CERT_DIR to a known-good bundle.
- Pre-populate tlsConfig.RootCAs before loading cert dirs.
When it happens
Trigger: registry.ReadCertsDirectory encounters a *.crt file, RootCAs is nil, and x509.SystemCertPool() returns an error — e.g. on a minimal/container environment without /etc/ssl/certs/ca-certificates.crt, or where that file exists but cannot be parsed.
Common situations: Running docker-trust inside a stripped-down container or scratch image with no CA bundle, an Alpine image without ca-certificates installed, a read-only filesystem blocking the bundle, or a corrupted CA bundle.
Related errors
- failed to retrieve context tls info: ca.pem seems invalid
- failed to retrieve context tls info
- TLS data for / / does not exist
- valid https URL required for trust server, got
- unable to get system cert pool
AI-assisted analysis of docker/cli@4f84911bfe (2026-08-07).
Data as JSON: /api/errors/0b2016d599206ae1.
Report an issue: GitHub.
Appendix: source
Thrown at cmd/docker-trust/internal/registry/registry.go:53
func loadTLSConfig(ctx context.Context, directory string, tlsConfig *tls.Config) error {
fs, err := os.ReadDir(directory)
if err != nil {
if os.IsNotExist(err) {
return nil
}
return invalidParam(err)
}
for _, f := range fs {
if ctx.Err() != nil {
return ctx.Err()
}
switch filepath.Ext(f.Name()) {
case ".crt":
if tlsConfig.RootCAs == nil {
systemPool, err := x509.SystemCertPool()
if err != nil {
return invalidParam(fmt.Errorf("unable to get system cert pool: %w", err))
}
tlsConfig.RootCAs = systemPool
}
fileName := filepath.Join(directory, f.Name())
logrus.Debugf("crt: %s", fileName)
data, err := os.ReadFile(fileName)
if err != nil {
return err
}
tlsConfig.RootCAs.AppendCertsFromPEM(data)
case ".cert":
certName := f.Name()
keyName := certName[:len(certName)-5] + ".key"
logrus.Debugf("cert: %s", filepath.Join(directory, certName))
if !hasFile(fs, keyName) {
return invalidParamf("missing key %s for client certificate %s. CA certificates must use the extension .crt", keyName, certName)
}
cert, err := tls.LoadX509KeyPair(filepath.Join(directory, certName), filepath.Join(directory, keyName))View on GitHub (pinned to 4f84911bfe)