{"record":{"id":"0b4d127ff34f20ae","repo":"hashicorp/nomad","slug":"failed-to-load-cert-key-pair-v-0b4d12","errorCode":null,"errorMessage":"Failed to load cert/key pair: %v","messagePattern":"Failed to load cert/key pair: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nomad/structs/config/tls.go","lineNumber":94,"sourceCode":"\tcacheLock   sync.Mutex\n\tcertificate *tls.Certificate\n}\n\n// LoadKeyPair reloads the TLS certificate based on the specified certificate\n// and key file. If successful, stores the certificate for further use.\nfunc (k *KeyLoader) LoadKeyPair(certFile, keyFile string) (*tls.Certificate, error) {\n\tk.cacheLock.Lock()\n\tdefer k.cacheLock.Unlock()\n\n\t// Allow downgrading\n\tif certFile == \"\" && keyFile == \"\" {\n\t\tk.certificate = nil\n\t\treturn nil, nil\n\t}\n\n\tcert, err := tls.LoadX509KeyPair(certFile, keyFile)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"Failed to load cert/key pair: %v\", err)\n\t}\n\n\tk.certificate = &cert\n\treturn k.certificate, nil\n}\n\nfunc (k *KeyLoader) GetCertificate() *tls.Certificate {\n\tk.cacheLock.Lock()\n\tdefer k.cacheLock.Unlock()\n\treturn k.certificate\n}\n\n// GetOutgoingCertificate fetches the currently-loaded certificate when\n// accepting a TLS connection. This currently does not consider information in\n// the ClientHello and only returns the certificate that was last loaded.\nfunc (k *KeyLoader) GetOutgoingCertificate(*tls.ClientHelloInfo) (*tls.Certificate, error) {\n\tk.cacheLock.Lock()\n\tdefer k.cacheLock.Unlock()","sourceCodeStart":76,"sourceCodeEnd":112,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/nomad/structs/config/tls.go#L76-L112","documentation":"TLSConfig.LoadKeyPair lazily loads the certificate and key from disk with tls.LoadX509KeyPair. If the files cannot be read, are missing, or the cert/key do not match, the underlying error is wrapped as 'Failed to load cert/key pair'.","triggerScenarios":"First call that needs the certificate (after the pair was configured) invokes LoadKeyPair and crypto/tls fails to read/parse certFile+keyFile, e.g. nonexistent path, bad PEM, or mismatched pair.","commonSituations":"Wrong paths after moving configs between hosts; cert renewed but key not updated (mismatch); unreadable file permissions; corrupt or truncated PEM files.","solutions":["Verify both cert_file and key_file paths exist and are readable by the Nomad agent user","Confirm cert and key are a matching pair: openssl x509 -noout -modulus -in cert.crt vs openssl rsa -noout -modulus -in key.key","Regenerate/re-export the PEM files if they are corrupt or in a non-PEM format"],"exampleFix":"// before\ntls {\n  cert_file = \"/etc/nomad/server.crt\"\n  key_file  = \"/etc/nomad/old-server.key\"\n}\n// after\ntls {\n  cert_file = \"/etc/nomad/server.crt\"\n  key_file  = \"/etc/nomad/server.key\"\n}","handlingStrategy":"validation","validationCode":"if _, err := tls.LoadX509KeyPair(cfg.TLS.CertFile, cfg.TLS.KeyFile); err != nil {\n    return fmt.Errorf(\"preflight cert/key check failed: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"cert, err := tlsCfg.LoadKeyPair()\nif err != nil {\n    return fmt.Errorf(\"tls setup failed: %w (verify cert_file/key_file paths, permissions, and pair match)\", err)\n}","preventionTips":["Deploy cert and key files together so they always match","Check file readability as the agent's service user","Run openssl x509/openssl rsa modulus comparison before rollout","Preflight-load the pair at config-load time, not first use"],"tags":["tls","certificates","config"],"backgroundTag":"tls-certificate-load-failed","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"}