hashicorp/nomad · critical
failed to parse CA file: %w
Error message
failed to parse CA file: %w
What it means
newTLSMetrics (used by the agent to report TLS certificate/CA expiry metrics) parses the configured CA file with caFileExpiry (x509 PEM parsing). If the CA file cannot be read or parsed as a valid PEM certificate, the error is wrapped with 'failed to parse CA file:'. Agent startup via NewAgent fails.
Source
Thrown at command/agent/tls_metrics.go:58
// newTLSMetrics creates a new tlsMetrics instance that can be used to
// periodically emit TLS certificate expiry metrics. It is the callers
// responsibility to ensure the passed TLS configuration is not-nil and valid.
//
// Once created, the start and stop methods can be used to control the
// background emission of metrics. The caller should create a new instance and
// stop the old instance each time TLS certificates are reloaded.
func newTLSMetrics(logger hclog.Logger, tlsCfg *config.TLSConfig, labels []metrics.Label) (*tlsMetrics, error) {
t := tlsMetrics{
labels: labels,
logger: logger,
stopCh: make(chan struct{}),
}
exp, err := caFileExpiry(tlsCfg.CAFile)
if err != nil {
return nil, fmt.Errorf("failed to parse CA file: %w", err)
}
t.caExpiry = exp
// Using LoadX509KeyPair helps with parsing files with combined
// public/private keys, whitespace, etc.
certs, err := tls.LoadX509KeyPair(tlsCfg.CertFile, tlsCfg.KeyFile)
if err != nil {
return nil, fmt.Errorf("failed to parse cert key pair: %w", err)
}
// we are guaranteed to have at least 1 cert if LoadX509 succeeds
c, err := x509.ParseCertificate(certs.Certificate[0])
if err != nil {
return nil, fmt.Errorf("failed to parse cert bytes: %w", err)
}
t.certExpiry = c.NotAfter
return &t, nilView on GitHub (pinned to 482b49bf1a)
Solutions
- Verify the path in tls.ca_file exists and is readable by the Nomad process user
- Confirm the file contains a PEM certificate block (-----BEGIN CERTIFICATE-----); use 'openssl x509 -in <file> -noout' to test
- Regenerate or re-fetch the CA bundle if corrupted or empty
- Check that the CA file is mounted/copied into containers before the agent starts
Defensive patterns
Strategy: validation
Validate before calling
pemBytes, err := os.ReadFile(caFile)
if err != nil { return err }
if block, _ := pem.Decode(pemBytes); block == nil || block.Type != "CERTIFICATE" {
return fmt.Errorf("%s is not a PEM certificate", caFile)
}
if _, err := x509.ParseCertificate(block.Bytes); err != nil { return err } Try / catch
exp, err := caFileExpiry(tlsCfg.CAFile)
if err != nil {
return fmt.Errorf("failed to parse CA file %q: %w", tlsCfg.CAFile, err)
} Prevention
- Test CA files with 'openssl x509 -in <file> -noout' before deploying
- Ensure the file is mounted and readable by the agent user before startup
- Deploy CA bundles atomically (write temp file, rename)
- Verify secret-rendering tools finished before agent start
When it happens
Trigger: tls { ca_file = "..." } pointing to a missing, unreadable, empty, or non-PEM file when the agent starts and newTLSMetrics is invoked.
Common situations: Wrong path in ca_file (typo, container path not mounted), CA file containing an intermediate-only or private-key PEM, file permissions blocking read, secret not yet rendered by a vault/template.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- failed to parse cert key pair: %w
- failed to parse cert bytes: %w
- invalid certificate: %s not in expected %s
- no PEM-encoded data found
- common name value not provided
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/43963e22fc68f09f.
Report an issue: GitHub.