argoproj/argo-workflows · error
failed to read certificate file: %w
Error message
failed to read certificate file: %w
What it means
When the rest.Config has no inline CertData, ClaimSetWithX509 falls back to reading the certificate from restConfig.CertFile with os.ReadFile. If the file cannot be opened (missing, unreadable, wrong path), the OS error is wrapped as 'failed to read certificate file: %w'. The operation aborts because no identity claims can be derived without the certificate.
Source
Thrown at server/auth/serviceaccount/claims.go:91
func ClaimSetWithX509(restConfig *rest.Config) (*types.Claims, error) {
var cert *x509.Certificate
var err error
if len(restConfig.CertData) > 0 {
// Decode certificate from memory data
block, _ := pem.Decode(restConfig.CertData)
if block == nil || block.Type != "CERTIFICATE" {
return nil, fmt.Errorf("failed to parse certificate PEM")
}
cert, err = x509.ParseCertificate(block.Bytes)
if err != nil {
return nil, fmt.Errorf("failed to parse certificate: %w", err)
}
} else {
// Load certificate from file
data, err := os.ReadFile(restConfig.CertFile)
if err != nil {
return nil, fmt.Errorf("failed to read certificate file: %w", err)
}
block, _ := pem.Decode(data)
if block == nil || block.Type != "CERTIFICATE" {
return nil, fmt.Errorf("failed to parse certificate PEM")
}
cert, err = x509.ParseCertificate(block.Bytes)
if err != nil {
return nil, fmt.Errorf("failed to parse certificate: %w", err)
}
}
if cert == nil {
return nil, fmt.Errorf("failed to parse certificate")
}
// Extract username from CommonName (CN)
username := cert.Subject.CommonName
View on GitHub (pinned to 35bff19146)
Solutions
- Check the file exists and is readable: `ls -l <CertFile path>` and `head -1 <path>` should show '-----BEGIN CERTIFICATE-----'
- Fix the kubeconfig's users[].user.client-certificate path or mount the client cert secret into the argo-server pod
- If running in-cluster, provide inline CertData (base64 of the cert) instead of a file path so no filesystem dependency exists
Example fix
// before restConfig.CertFile = "/secrets/tls/client.crt" // file not mounted // after: embed the data so no file read is needed restConfig.CertData = clientCertPEMBytes
Defensive patterns
Strategy: validation
Validate before calling
func validateCertFile(path string) error {
data, err := os.ReadFile(path)
if err != nil {
return fmt.Errorf("cert file %q unreadable: %w", path, err)
}
return nil
}
// call before constructing rest.Config with CertFile Try / catch
claims, err := ClaimSetWithX509(restConfig)
if err != nil && strings.Contains(err.Error(), "failed to read certificate file") {
// fall back or surface a config-fix message
} Prevention
- Use absolute, stable paths for client certs (e.g. /var/run/secrets/... mounts)
- Prefer inline CertData over CertFile in containers to avoid mount-order issues
- Check secret volume mounts are ready before argo-server starts (init containers/dependsOn)
- Test file readability as the same user/UID the server runs as
When it happens
Trigger: restConfig.CertData is empty, restConfig.CertFile points to a path that does not exist, is a directory, or the process lacks read permission, so os.ReadFile returns an error which is wrapped and returned.
Common situations: Mounted secret volume path changed or not mounted yet; client-certificate file deleted after kubeconfig was flattened; argo-server running with a different service account that cannot read the cert path; typo in certFile path in kubeconfig.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- --client-certificate and --client-key must be provided toget
- failed to parse certificate: %w
- invalid expiry date in Kubeconfig. %w
- failed to read certificate authority: %w
- failed to create folder path: %w
AI-assisted analysis of argoproj/argo-workflows@35bff19146 (2026-09-03).
Data as JSON: /api/errors/01b296d130cd73fa.
Report an issue: GitHub.