{"record":{"id":"2ed6665eee855de7","repo":"hashicorp/nomad","slug":"failed-to-decode-s-pem-block","errorCode":null,"errorMessage":"failed to decode %s PEM block","messagePattern":"failed to decode (.+?) PEM block","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"lib/auth/oidc/client_assertion.go","lineNumber":176,"sourceCode":"\tif k.PemCertFile != \"\" {\n\t\tsource = \"PemCertFile\"\n\t\tbts, err = os.ReadFile(k.PemCertFile)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"error reading %s: %w\", source, err)\n\t\t}\n\t}\n\t// or pem string\n\tif k.PemCert != \"\" {\n\t\tsource = \"PemCert\"\n\t\tbts = []byte(k.PemCert)\n\t}\n\n\t// ensure newlines around pem header/footer\n\tbts = newlineHeaders(bts)\n\n\tblock, _ := pem.Decode(bts)\n\tif block == nil {\n\t\treturn nil, fmt.Errorf(\"failed to decode %s PEM block\", source)\n\t}\n\tcert, err := x509.ParseCertificate(block.Bytes)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to parse %s bytes: %w\", source, err)\n\t}\n\tnow := time.Now()\n\tif now.Before(cert.NotBefore) || now.After(cert.NotAfter) {\n\t\treturn nil, errors.New(\"certificate has expired or is not yet valid\")\n\t}\n\treturn cert, nil\n}\n\n// hashKeyID derives a \"certificate thumbprint\" that the OIDC provider uses\n// to find the certificate to verify the private key JWT signature.\n// https://datatracker.ietf.org/doc/html/rfc7515#section-4.1.7\nfunc hashKeyID(cert *x509.Certificate, header structs.OIDCClientAssertionKeyIDHeader) (string, error) {\n\tvar hasher hash.Hash\n\tswitch header {","sourceCodeStart":158,"sourceCodeEnd":194,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/lib/auth/oidc/client_assertion.go#L158-L194","documentation":"getCassCert read the cert bytes but pem.Decode found no valid PEM block — the data lacks recognizable BEGIN/END certificate markers or the base64 body is invalid. newlineHeaders fixes surrounding newlines, so the content itself is not valid PEM.","triggerScenarios":"BuildClientAssertionJWT → getCassCert after reading PemCertFile/PemCert, when the bytes are not a PEM certificate (raw DER, JSON-wrapped secret, empty file, HTML error page).","commonSituations":"Secret store returned the cert base64-encoded and it was pasted without decoding; file contains the key instead of the cert; templating stripped the PEM headers; empty placeholder file.","solutions":["Verify the content starts with `-----BEGIN CERTIFICATE-----` and ends with `-----END CERTIFICATE-----`; re-export with `openssl x509 -in cert.crt -out cert.pem`.","If the value is base64, decode it first: `base64 -d cert.b64 > cert.pem`.","Check the file is non-empty and contains the certificate, not the private key or an error page."],"exampleFix":"// before: base64 blob pasted as PemCert\nPemCert: \"LS0tLS1CRUdJTi...\"\n// after: decoded PEM\nPemCert: \"-----BEGIN CERTIFICATE-----\\nMIID...\\n-----END CERTIFICATE-----\"","handlingStrategy":"validation","validationCode":"func validateCertPEM(s string) error {\n  blk, _ := pem.Decode([]byte(s))\n  if blk == nil || blk.Type != \"CERTIFICATE\" {\n    return fmt.Errorf(\"value is not a PEM certificate\")\n  }\n  _, err := x509.ParseCertificate(blk.Bytes)\n  return err\n}","typeGuard":"func isPEMCertificate(s string) bool {\n  blk, _ := pem.Decode([]byte(s))\n  return blk != nil && blk.Type == \"CERTIFICATE\"\n}","tryCatchPattern":"key, err := getCassCert(k)\nif err != nil && strings.Contains(err.Error(), \"failed to decode\") {\n  return fmt.Errorf(\"cert value is not PEM; decode base64 or re-export via openssl x509: %w\", err)\n}","preventionTips":["Decode base64-wrapped secrets before storing them in PemCert/PemCertFile.","Verify files begin with `-----BEGIN CERTIFICATE-----` after templating.","Validate with `openssl x509 -in cert.pem -noout` before configuring."],"tags":["oidc","client-assertion","pem","certificate"],"backgroundTag":"invalid-pem-key","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"}