{"record":{"id":"75a0e34dce4ae495","repo":"gofr-dev/gofr","slug":"failed-to-read-ca-certificate-from-s-w","errorCode":null,"errorMessage":"failed to read CA certificate from %s: %w","messagePattern":"failed to read CA certificate from (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/gofr/datasource/sql/sql.go","lineNumber":517,"sourceCode":"\t}\n\n\tcaCertPath := os.Getenv(\"DB_TLS_CA_CERT\")\n\tif caCertPath == \"\" {\n\t\tlogger.Warn(\"DB_SSL_MODE=verify-ca requires DB_TLS_CA_CERT. Falling back to system CA pool\")\n\n\t\t// Use system CA pool\n\t\ttlsConfig := &tls.Config{\n\t\t\tServerName: getServerName(dbConfig.HostName),\n\t\t\tMinVersion: tls.VersionTLS12,\n\t\t}\n\n\t\treturn mysql.RegisterTLSConfig(\"custom\", tlsConfig)\n\t}\n\n\t// Load custom CA certificate\n\tcaCert, err := os.ReadFile(caCertPath) //nolint:gosec // caCertPath is an operator-supplied configuration path, not user input\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to read CA certificate from %s: %w\", caCertPath, err)\n\t}\n\n\tcaCertPool := x509.NewCertPool()\n\tif !caCertPool.AppendCertsFromPEM(caCert) {\n\t\treturn errFailedCACerts\n\t}\n\n\ttlsConfig := &tls.Config{\n\t\tRootCAs:    caCertPool,\n\t\tServerName: dbConfig.HostName,\n\t\tMinVersion: tls.VersionTLS12,\n\t}\n\n\t// Optional: Support client certificates (mutual TLS)\n\tclientCertPath := os.Getenv(\"DB_TLS_CLIENT_CERT\")\n\tclientKeyPath := os.Getenv(\"DB_TLS_CLIENT_KEY\")\n\n\tif clientCertPath != \"\" && clientKeyPath != \"\" {","sourceCodeStart":499,"sourceCodeEnd":535,"githubUrl":"https://github.com/gofr-dev/gofr/blob/187eb24962502e91f1fee856230670958b66e89c/pkg/gofr/datasource/sql/sql.go#L499-L535","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","solutions":["Verify the file exists at DB_TLS_CA_CERT_PATH (ls -l the path inside the container).","Fix file permissions so the process user can read the cert (chmod 644 / correct secret mount mode).","Use an absolute path; confirm the container volume/secret is mounted.","Correct any typo in the DB_TLS_CA_CERT_PATH environment variable."],"exampleFix":"// before\nDB_TLS_CA_CERT_PATH=/etc/ssl/certs/ca.pem  (file not mounted)\n// after\ndocker run -v ./certs/ca.pem:/etc/ssl/certs/ca.pem:ro ... DB_TLS_CA_CERT_PATH=/etc/ssl/certs/ca.pem","handlingStrategy":"validation","validationCode":"path := os.Getenv(\"DB_TLS_CA_CERT_PATH\")\nif path != \"\" {\n    if fi, err := os.Stat(path); err != nil || fi.IsDir() {\n        return fmt.Errorf(\"CA cert path %q unreadable\", path)\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use absolute paths for cert files in containers.","Assert secret mounts exist in entrypoint/startup scripts.","Run containers with the cert directory mounted read-only and correct ownership."],"tags":["tls","mysql","filesystem","configuration"],"backgroundTag":"certificate-file-not-found","analyzedSha":"187eb24962502e91f1fee856230670958b66e89c","analyzedAt":"2026-09-01T20:34:54.554Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}