{"record":{"id":"1f02985664c54050","repo":"hashicorp/nomad","slug":"failed-to-parse-any-valid-certificates-in-ca-file","errorCode":null,"errorMessage":"Failed to parse any valid certificates in CA file: %s","messagePattern":"Failed to parse any valid certificates in CA file: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"helper/tlsutil/config.go","lineNumber":191,"sourceCode":"\n// AppendCA opens and parses the CA file and adds the certificates to\n// the provided CertPool.\nfunc (c *Config) AppendCA(pool *x509.CertPool) error {\n\tif c.CAFile == \"\" {\n\t\treturn nil\n\t}\n\n\t// Read the file\n\tdata, err := os.ReadFile(c.CAFile)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"Failed to read CA file: %v\", err)\n\t}\n\n\t// Read certificates and return an error if no valid certificates were\n\t// found. Unfortunately it is very difficult to return meaningful\n\t// errors as PEM files are extremely permissive.\n\tif !pool.AppendCertsFromPEM(data) {\n\t\treturn fmt.Errorf(\"Failed to parse any valid certificates in CA file: %s\", c.CAFile)\n\t}\n\n\treturn nil\n}\n\n// LoadKeyPair is used to open and parse a certificate and key file\nfunc (c *Config) LoadKeyPair() (*tls.Certificate, error) {\n\tif c.CertFile == \"\" || c.KeyFile == \"\" {\n\t\treturn nil, nil\n\t}\n\n\tif c.KeyLoader == nil {\n\t\treturn nil, fmt.Errorf(\"No Keyloader object to perform LoadKeyPair\")\n\t}\n\n\tcert, err := c.KeyLoader.LoadKeyPair(c.CertFile, c.KeyFile)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"Failed to load cert/key pair: %v\", err)","sourceCodeStart":173,"sourceCodeEnd":209,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/helper/tlsutil/config.go#L173-L209","documentation":"After reading CAFile, AppendCA feeds the bytes to pool.AppendCertsFromPEM, which returns false if not even one valid certificate could be parsed. Because PEM parsing is lenient and gives no detail, the library reports this opaque error naming the file. It means the CA file exists but contains no usable certificate.","triggerScenarios":"CAFile points to an existing readable file whose contents contain zero PEM blocks parseable as certificates — e.g. an empty file, a private key instead of a cert, plain text, HTML error page downloaded instead of a cert, or only unrelated PEM blocks.","commonSituations":"Downloading a CA bundle via curl that saved an error page; concatenating the wrong files; exporting a key instead of a certificate; config pointing at the client key file instead of the CA bundle; truncated copy/paste of the PEM.","solutions":["Inspect the file: it must contain one or more '-----BEGIN CERTIFICATE-----' blocks (openssl x509 -in <file> -noout -text).","Regenerate/re-download the CA bundle from the correct source and verify with openssl.","Ensure you point CAFile at the CA certificate(s), not the private key or leaf cert chain only.","Validate the whole bundle with openssl verify / openssl storeutl to catch malformed entries."],"exampleFix":"// before\nconfig.CAFile = \"/etc/tls/server.key\" // a private key, no certificates\n// after\nconfig.CAFile = \"/etc/tls/ca.crt\" // PEM certificate bundle","handlingStrategy":"validation","validationCode":"func validateCABundle(path string) error {\n    data, err := os.ReadFile(path)\n    if err != nil { return err }\n    if !x509.NewCertPool().AppendCertsFromPEM(data) {\n        return fmt.Errorf(\"%s contains no valid PEM certificates\", path)\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":"tlsCfg, err := tlsConf.IncomingTLSConfig()\nif err != nil && strings.Contains(err.Error(), \"Failed to parse any valid certificates\") {\n    return fmt.Errorf(\"CA bundle at %s is not a PEM cert file: %w\", cfg.CAFile, err)\n}","preventionTips":["Verify CA files with `openssl x509 -in <file> -noout` in CI before shipping config.","Point CAFile at certificates, never at keys or CSR files.","Check downloaded bundles are actual PEM (guard against HTML error pages) with a content sniff.","Keep a known-good CA bundle and validate replacements against it before swapping."],"tags":["tls","certificate","pem","configuration"],"backgroundTag":"invalid-pem-certificate","analyzedSha":"482b49bf1aec006f089bcfc7e632d8f6ac303e5e","analyzedAt":"2026-09-04T07:54:14.808Z","contentChangedAt":"2026-09-04T07:54:14.808Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}