gofr-dev/gofr · error

failed to read CA certificate from %s: %w

Error message

failed to read CA certificate from %s: %w

What it means

Raised in registerMySQLTLSConfig when os.ReadFile fails on the DB_TLS_CA_CERT_PATH configured for MySQL TLS. The wrapped os error tells you whether the file is missing, permission-denied, or is a directory. gofr cannot build the custom TLS config without the CA material.

Source

Thrown at pkg/gofr/datasource/sql/sql.go:517

	}

	caCertPath := os.Getenv("DB_TLS_CA_CERT")
	if caCertPath == "" {
		logger.Warn("DB_SSL_MODE=verify-ca requires DB_TLS_CA_CERT. Falling back to system CA pool")

		// Use system CA pool
		tlsConfig := &tls.Config{
			ServerName: getServerName(dbConfig.HostName),
			MinVersion: tls.VersionTLS12,
		}

		return mysql.RegisterTLSConfig("custom", tlsConfig)
	}

	// Load custom CA certificate
	caCert, err := os.ReadFile(caCertPath) //nolint:gosec // caCertPath is an operator-supplied configuration path, not user input
	if err != nil {
		return fmt.Errorf("failed to read CA certificate from %s: %w", caCertPath, err)
	}

	caCertPool := x509.NewCertPool()
	if !caCertPool.AppendCertsFromPEM(caCert) {
		return errFailedCACerts
	}

	tlsConfig := &tls.Config{
		RootCAs:    caCertPool,
		ServerName: dbConfig.HostName,
		MinVersion: tls.VersionTLS12,
	}

	// Optional: Support client certificates (mutual TLS)
	clientCertPath := os.Getenv("DB_TLS_CLIENT_CERT")
	clientKeyPath := os.Getenv("DB_TLS_CLIENT_KEY")

	if clientCertPath != "" && clientKeyPath != "" {

View on GitHub (pinned to 187eb24962)

Solutions

  1. Verify the file exists at DB_TLS_CA_CERT_PATH (ls -l the path inside the container).
  2. Fix file permissions so the process user can read the cert (chmod 644 / correct secret mount mode).
  3. Use an absolute path; confirm the container volume/secret is mounted.
  4. Correct any typo in the DB_TLS_CA_CERT_PATH environment variable.

Example fix

// before
DB_TLS_CA_CERT_PATH=/etc/ssl/certs/ca.pem  (file not mounted)
// after
docker run -v ./certs/ca.pem:/etc/ssl/certs/ca.pem:ro ... DB_TLS_CA_CERT_PATH=/etc/ssl/certs/ca.pem
Defensive patterns

Strategy: validation

Validate before calling

path := os.Getenv("DB_TLS_CA_CERT_PATH")
if path != "" {
    if fi, err := os.Stat(path); err != nil || fi.IsDir() {
        return fmt.Errorf("CA cert path %q unreadable", path)
    }
}

Prevention

When it happens

Trigger: NewSQL (mysql dialect) with DB_TLS_CA_CERT_PATH set to a nonexistent path, a path in an unmounted volume, or a file the process user cannot read (permission denied).

Common situations: Typo in the cert path env var, secret not mounted into the container, running the container as a non-root user without read access, or relative path used where a working directory differs.

Understand the failure class

Related errors


AI-assisted analysis of gofr-dev/gofr@187eb24962 (2026-09-01). Data as JSON: /api/errors/75a0e34dce4ae495. Report an issue: GitHub.