hashicorp/nomad · error

Failed to read CA file: %v

Error message

Failed to read CA file: %v

What it means

AppendCA reads the CAFile from a TLS Config and appends its PEM certificates to the certificate pool. This error wraps any failure reading that file from disk (os.ReadFile). It means the configured CA bundle path could not be opened or read, so no CA certificates can be loaded for TLS verification.

Source

Thrown at helper/tlsutil/config.go:184

		CertFile:             newConf.CertFile,
		KeyFile:              newConf.KeyFile,
		KeyLoader:            newConf.GetKeyLoader(),
		CipherSuites:         ciphers,
		MinVersion:           minVersion,
	}, nil
}

// AppendCA opens and parses the CA file and adds the certificates to
// the provided CertPool.
func (c *Config) AppendCA(pool *x509.CertPool) error {
	if c.CAFile == "" {
		return nil
	}

	// Read the file
	data, err := os.ReadFile(c.CAFile)
	if err != nil {
		return fmt.Errorf("Failed to read CA file: %v", err)
	}

	// Read certificates and return an error if no valid certificates were
	// found. Unfortunately it is very difficult to return meaningful
	// errors as PEM files are extremely permissive.
	if !pool.AppendCertsFromPEM(data) {
		return fmt.Errorf("Failed to parse any valid certificates in CA file: %s", c.CAFile)
	}

	return nil
}

// LoadKeyPair is used to open and parse a certificate and key file
func (c *Config) LoadKeyPair() (*tls.Certificate, error) {
	if c.CertFile == "" || c.KeyFile == "" {
		return nil, nil
	}

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Verify the path in CAFile is absolute and correct, and that the file exists (ls -l <path>).
  2. Fix file permissions/ownership so the process user can read it.
  3. Ensure the CA file is mounted/copied into containers or the correct secret is referenced.
  4. Confirm CAFile is a regular file, not a directory, and re-check config after rotation.

Example fix

// before
config.CAFile = "ca.pem" // relative path; file not found at runtime
// after
config.CAFile = "/etc/consul/tls/ca.pem" // absolute, existing, readable path
Defensive patterns

Strategy: validation

Validate before calling

func validateCAFile(path string) error {
    fi, err := os.Stat(path)
    if err != nil { return fmt.Errorf("CA file %q: %w", path, err) }
    if fi.IsDir() { return fmt.Errorf("CAFile %q is a directory", path) }
    f, err := os.Open(path)
    if err != nil { return fmt.Errorf("CA file not readable: %w", err) }
    f.Close()
    return nil
}
// call before building config: if err := validateCAFile(cfg.CAFile); err != nil { ... }

Try / catch

tlsCfg, err := tlsConf.OutgoingTLSConfig()
if err != nil && strings.Contains(err.Error(), "Failed to read CA file") {
    return fmt.Errorf("misconfigured CA path: %w", err)
}

Prevention

When it happens

Trigger: OutgoingTLSConfig or IncomingTLSConfig is built with Config.CAFile set, but os.ReadFile(c.CAFile) fails — the file does not exist, the path is wrong, permissions deny read, or it is a directory.

Common situations: Typo in CAFile path; CA file not mounted into a container; wrong working directory making a relative path invalid; file removed by secret rotation; running as a user lacking read permission on the cert.

Related errors


AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04). Data as JSON: /api/errors/da81bd4b8bda2cbf. Report an issue: GitHub.