{"record":{"id":"abe7ba7408f3bfb6","repo":"caddyserver/caddy","slug":"parsing-certificate-in-s-v","errorCode":null,"errorMessage":"parsing certificate in %s: %v","messagePattern":"parsing certificate in (.+?): (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"modules/caddytls/capools.go","lineNumber":167,"sourceCode":"\tvar certs []*x509.Certificate\n\tfor _, pemFile := range f.TrustedCACertPEMFiles {\n\t\tpemContents, err := os.ReadFile(pemFile)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"reading %s: %v\", pemFile, err)\n\t\t}\n\t\t// Parse PEM to extract certificates\n\t\tfor len(pemContents) > 0 {\n\t\t\tvar block *pem.Block\n\t\t\tblock, pemContents = pem.Decode(pemContents)\n\t\t\tif block == nil {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tif block.Type != \"CERTIFICATE\" {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tcert, err := x509.ParseCertificate(block.Bytes)\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"parsing certificate in %s: %v\", pemFile, err)\n\t\t\t}\n\t\t\tcaPool.AddCert(cert)\n\t\t\tcerts = append(certs, cert)\n\t\t}\n\t}\n\tf.pool = caPool\n\tf.certs = certs\n\treturn nil\n}\n\n// Syntax:\n//\n//\ttrust_pool file [<pem_file>...] {\n//\t\tpem_file <pem_file>...\n//\t}\n//\n// The 'pem_file' directive can be specified multiple times.\nfunc (fcap *FileCAPool) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {","sourceCodeStart":149,"sourceCodeEnd":185,"githubUrl":"https://github.com/caddyserver/caddy/blob/50e54ee279aa1e504fe218ca49ab6ae16c100410/modules/caddytls/capools.go#L149-L185","documentation":"FileCAPool.Provision successfully read the PEM file and found CERTIFICATE blocks, but x509.ParseCertificate failed on one block's DER payload. The file exists and is PEM-shaped, yet at least one certificate inside is corrupt or truncated — the wrapped error gives the precise parse failure.","triggerScenarios":"A trusted CA PEM file where a certificate was partially overwritten, has flipped bytes from a bad copy-paste (line truncation, missing base64 padding), or contains a CERTIFICATE block that is not actually X.509 (e.g. a converted key or CSR mislabeled as a certificate).","commonSituations":"Hand-concatenated CA bundles with a broken intermediate; files edited in place where one line got mangled; certificate chains downloaded in the wrong format (PKCS#7 saved as .pem without conversion).","solutions":["Validate each certificate in the file: openssl crl2pkcs7 -nocrl -certfile ca.pem | openssl pkcs7 -print_certs -noout, or split the bundle and parse each block with openssl x509 -noout -in <block>.","Re-download or re-export the CA bundle from the authoritative source.","If the bundle contains PKCS#7 content, convert first: openssl pkcs7 -in bundle.p7b -print_certs -out ca.pem.","Remove non-certificate blocks (keys, CSRs) from the file."],"exampleFix":"# before: corrupt block inside bundle\n# (one BEGIN/END CERTIFICATE section is truncated)\n\n# after: regenerate a clean PEM bundle\nopenssl pkcs7 -in bundle.p7b -print_certs -out /etc/caddy/ca.pem\n# then verify every cert parses:\nawk 'BEGIN{c=0} /BEGIN CERT/{c++} /END CERT/{print \"cert\",c}' /etc/caddy/ca.pem\nopenssl crl2pkcs7 -nocrl -certfile /etc/caddy/ca.pem | openssl pkcs7 -print_certs -noout","handlingStrategy":"validation","validationCode":"// Verify every CERTIFICATE block parses before Caddy loads the file.\ndata, _ := os.ReadFile(pemFile)\nrest := data\nfor {\n    var block *pem.Block\n    block, rest = pem.Decode(rest)\n    if block == nil {\n        break\n    }\n    if block.Type != \"CERTIFICATE\" {\n        continue\n    }\n    if _, err := x509.ParseCertificate(block.Bytes); err != nil {\n        return fmt.Errorf(\"bad cert in %s: %v\", pemFile, err)\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Validate CA bundles in CI with openssl pkcs7 -print_certs after any regeneration.","Never hand-edit PEM bundles; regenerate from the source of truth.","Convert PKCS#7 bundles to PEM explicitly rather than renaming files."],"tags":["tls","client-auth","certificates","pem","parsing"],"backgroundTag":null,"analyzedSha":"50e54ee279aa1e504fe218ca49ab6ae16c100410","analyzedAt":"2026-08-15T09:20:21.641Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}