{"record":{"id":"01736c51ada90627","repo":"nats-io/nats-server","slug":"unexpected-pem-certificate-type-s","errorCode":null,"errorMessage":"unexpected PEM certificate type: %s","messagePattern":"unexpected PEM certificate type: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/ocsp.go","lineNumber":887,"sourceCode":"\treturn nil\n}\n\nfunc parseCertPEM(name string) ([]*x509.Certificate, error) {\n\tdata, err := os.ReadFile(name)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tvar pemBytes []byte\n\n\tvar block *pem.Block\n\tfor len(data) != 0 {\n\t\tblock, data = pem.Decode(data)\n\t\tif block == nil {\n\t\t\tbreak\n\t\t}\n\t\tif block.Type != \"CERTIFICATE\" {\n\t\t\treturn nil, fmt.Errorf(\"unexpected PEM certificate type: %s\", block.Type)\n\t\t}\n\n\t\tpemBytes = append(pemBytes, block.Bytes...)\n\t}\n\n\treturn x509.ParseCertificates(pemBytes)\n}\n\n// getOCSPIssuerLocally determines a leaf's issuer from locally configured certificates\nfunc getOCSPIssuerLocally(trustedCAs []*x509.Certificate, certBundle []*x509.Certificate) (*x509.Certificate, error) {\n\tvar vOpts x509.VerifyOptions\n\tvar leaf *x509.Certificate\n\ttrustedCAPool := x509.NewCertPool()\n\n\t// Require Leaf as first cert in bundle\n\tif len(certBundle) > 0 {\n\t\tleaf = certBundle[0]\n\t} else {","sourceCodeStart":869,"sourceCodeEnd":905,"githubUrl":"https://github.com/nats-io/nats-server/blob/3a66a489d262bf89b71a71c955c94920394532f3/server/ocsp.go#L869-L905","documentation":"parseCertPEM decodes a PEM file expected to contain only CERTIFICATE blocks. When a PEM block of a different type (e.g. PRIVATE KEY, CERTIFICATE REQUEST) is found, it aborts because the file was passed as a CA trust store (ocsp ca_file) and non-certificate material cannot be trusted as an issuer.","triggerScenarios":"Calling getOCSPIssuer with a ca_file whose PEM contents include a block with block.Type != \"CERTIFICATE\"; parseCertPEM returns this error, which is then wrapped as \"failed to parse ca_file\".","commonSituations":"Pointing ocsp ca_file at a combined key+cert file (fullchain with private key), a CSR file, or a bundle containing a legacy 'X509 CERTIFICATE' typed block instead of the plain public CA cert PEM.","solutions":["Ensure ca_file contains ONLY certificates in PEM format (BEGIN CERTIFICATE blocks)","Split key material out of the file; keep the private key in the cert/key file, not the CA file","Re-export the CA with `openssl x509 -in ca.crt -out ca.crt` to normalize the PEM block header"],"exampleFix":"// before\nocsp_ca_file: /etc/nats/server-key.pem  // contains PRIVATE KEY block\n// after\nocsp_ca_file: /etc/nats/ca-bundle.pem   // only BEGIN CERTIFICATE blocks","handlingStrategy":"validation","validationCode":"pemData, _ := os.ReadFile(caFile)\nfor rest := pemData; len(rest) > 0; {\n    var b *pem.Block\n    b, rest = pem.Decode(rest)\n    if b == nil { break }\n    if b.Type != \"CERTIFICATE\" { return fmt.Errorf(\"%s contains non-certificate PEM block %q\", caFile, b.Type) }\n}","typeGuard":"func isCertPEMType(b *pem.Block) bool { return b != nil && b.Type == \"CERTIFICATE\" }","tryCatchPattern":null,"preventionTips":["Keep CA trust files separate from private key files","Validate PEM files with openssl before deploying","Use only BEGIN CERTIFICATE blocks in ca_file"],"tags":["tls","pem","ocsp","certificate-parsing"],"backgroundTag":"invalid-pem-certificate","analyzedSha":"3a66a489d262bf89b71a71c955c94920394532f3","analyzedAt":"2026-09-02T04:41:54.247Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}