{"record":{"id":"be382ed541a22e1a","repo":"hashicorp/nomad","slug":"no-pem-encoded-data-found","errorCode":null,"errorMessage":"no PEM-encoded data found","messagePattern":"no PEM-encoded data found","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"command/agent/tls_metrics.go","lineNumber":144,"sourceCode":"\t\tmetrics.SetGaugeWithLabels(\n\t\t\t[]string{\"agent\", \"tls\", \"ca\", \"expiration_seconds\"},\n\t\t\tfloat32(time.Until(t.caExpiry).Seconds()),\n\t\t\tt.labels,\n\t\t)\n\t}\n}\n\n// certFileExpiry reads a PEM-encoded certificate file and returns the NotAfter\n// time of the certificate.\nfunc caFileExpiry(path string) (time.Time, error) {\n\tdata, err := os.ReadFile(path)\n\tif err != nil {\n\t\treturn time.Time{}, fmt.Errorf(\"failed to read file: %w\", err)\n\t}\n\n\tblock, _ := pem.Decode(data)\n\tif block == nil {\n\t\treturn time.Time{}, errors.New(\"no PEM-encoded data found\")\n\t}\n\n\tcert, err := x509.ParseCertificate(block.Bytes)\n\tif err != nil {\n\t\treturn time.Time{}, fmt.Errorf(\"failed to parse certificate: %w\", err)\n\t}\n\n\treturn cert.NotAfter, nil\n}\n","sourceCodeStart":126,"sourceCodeEnd":154,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/command/agent/tls_metrics.go#L126-L154","documentation":"caFileExpiry in command/agent/tls_metrics.go reads a CA certificate file for TLS expiry metrics and decodes the first PEM block. If pem.Decode finds no PEM data (block == nil), it returns this error, meaning the file is not PEM-encoded (or is empty/garbage) and certificate expiry cannot be computed.","triggerScenarios":"Configuring the agent's TLS CA file path (caFile) to a file that contains DER binary, an empty file, a private key format pem.Decode rejects, or plain text — then TLS metrics initialization (newTLSMetrics) invokes caFileExpiry.","commonSituations":"Pointing ca_file at a DER-encoded .crt (common from some CAs), at a directory or socket, at a bundle with only non-certificate PEM that pem.Decode can't parse, or a file truncated by a failed copy/download.","solutions":["Ensure the file contains a PEM-encoded certificate: it should start with `-----BEGIN CERTIFICATE-----`; convert DER to PEM with `openssl x509 -inform der -in ca.crt -out ca.pem`.","Verify the file path in the agent TLS config points to the CA cert, not the key, directory, or an unrelated file.","Check the file is non-empty and intact (`openssl x509 -in ca.pem -noout -subject`) and re-copy if corrupted.","Confirm file permissions allow the Nomad agent user to read the file (though unreadable files usually surface as the read error instead)."],"exampleFix":"// before: DER binary cert\nca_file = \"/etc/ssl/ca.crt\"   // DER-encoded\n// after: convert to PEM\n// openssl x509 -inform der -in /etc/ssl/ca.crt -out /etc/ssl/ca.pem\nca_file = \"/etc/ssl/ca.pem\"","handlingStrategy":"validation","validationCode":"data, err := os.ReadFile(caFile)\nif err != nil {\n    return err\n}\nif block, _ := pem.Decode(data); block == nil {\n    return fmt.Errorf(\"%s is not PEM-encoded; convert with: openssl x509 -inform der -in %s -out ca.pem\", caFile, caFile)\n}","typeGuard":"func isPEMCertificate(data []byte) bool {\n    block, _ := pem.Decode(data)\n    return block != nil && block.Type == \"CERTIFICATE\"\n}","tryCatchPattern":"if _, err := tls.LoadX509KeyPair(certFile, keyFile); err != nil {\n    log.Printf(\"TLS files invalid: %v\", err)\n}\n// at runtime:\nif err != nil && strings.Contains(err.Error(), \"no PEM-encoded data found\") {\n    return fmt.Errorf(\"check ca_file %q: file is not PEM (DER or corrupt?)\", caFile)\n}","preventionTips":["Validate CA files with `openssl x509 -in ca.pem -noout` before deploying.","Point ca_file at a PEM-encoded certificate, never a DER .crt, key file, or directory.","Checksum certificates in config management to catch truncated downloads."],"tags":["tls","pem","certificate","file-parsing"],"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"}