docker/cli · error

failed to retrieve context tls info: ca.pem seems invalid

Error message

failed to retrieve context tls info: ca.pem seems invalid

What it means

Returned by Endpoint.tlsConfig when the context's stored CA PEM bytes fail to be parsed as a certificate. AppendCertsFromPEM returns false when the input is not valid PEM or contains no parseable certificates, so the trust pool cannot be built and TLS verification would be impossible.

Solutions

  1. Re-import or regenerate the context's CA certificate so ca.pem contains valid PEM CERTIFICATE blocks.
  2. Verify the file: 'openssl x509 -in ca.pem -noout -text' should succeed.
  3. Recreate the context with 'docker context create' pointing at valid TLS files.
Defensive patterns

Strategy: validation

Validate before calling

// Validate ca.pem is a usable certificate before creating the context.
pool := x509.NewCertPool()
if !pool.AppendCertsFromPEM(caBytes) {
    return errors.New("ca.pem is not a valid PEM certificate")
}

Type guard

func isValidCAPEM(b []byte) bool {
    pool := x509.NewCertPool()
    return pool.AppendCertsFromPEM(b)
}

Prevention

When it happens

Trigger: A docker context created with TLS material whose ca.pem is corrupt, truncated, empty, or not a PEM-encoded certificate. Importing a context archive with a malformed ca.pem. Manually editing the TLS files under ~/.docker/contexts/.../tls.

Common situations: A ca.pem was copied incompletely (e.g., missing the END CERTIFICATE line). The file contains a private key or arbitrary text instead of a certificate. A context was exported from a system with a different TLS setup and re-imported with bad data.

Understand the failure class

Related errors


AI-assisted analysis of docker/cli@4f84911bfe (2026-08-07). Data as JSON: /api/errors/f03796ec295efa68. Report an issue: GitHub.

Appendix: source

Thrown at cli/context/docker/load.go:54

		return Endpoint{}, err
	}
	return Endpoint{
		EndpointMeta: m,
		TLSData:      tlsData,
	}, nil
}

// tlsConfig extracts a context docker endpoint TLS config
func (ep *Endpoint) tlsConfig() (*tls.Config, error) {
	if ep.TLSData == nil && !ep.SkipTLSVerify {
		// there is no specific tls config
		return nil, nil
	}
	var tlsOpts []func(*tls.Config)
	if ep.TLSData != nil && ep.TLSData.CA != nil {
		certPool := x509.NewCertPool()
		if !certPool.AppendCertsFromPEM(ep.TLSData.CA) {
			return nil, errors.New("failed to retrieve context tls info: ca.pem seems invalid")
		}
		tlsOpts = append(tlsOpts, func(cfg *tls.Config) {
			cfg.RootCAs = certPool
		})
	}
	if ep.TLSData != nil && ep.TLSData.Key != nil && ep.TLSData.Cert != nil {
		keyBytes := ep.TLSData.Key
		pemBlock, _ := pem.Decode(keyBytes)
		if pemBlock == nil {
			return nil, errors.New("no valid private key found")
		}
		if x509.IsEncryptedPEMBlock(pemBlock) { //nolint:staticcheck // SA1019: x509.IsEncryptedPEMBlock is deprecated, and insecure by design
			return nil, errors.New("private key is encrypted - support for encrypted private keys has been removed, see https://docs.docker.com/go/deprecated/")
		}

		x509cert, err := tls.X509KeyPair(ep.TLSData.Cert, keyBytes)
		if err != nil {
			return nil, fmt.Errorf("failed to retrieve context tls info: %w", err)

View on GitHub (pinned to 4f84911bfe)