{"record":{"id":"4e8971e37095707e","repo":"Billionmail/BillionMail","slug":"failed-to-parse-certificate-info-v","errorCode":null,"errorMessage":"failed to parse certificate info: %v","messagePattern":"failed to parse certificate info: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/internal/service/mail_service/certificate.go","lineNumber":519,"sourceCode":"\t\tWhere(\"dns::jsonb ? $1\", public.FormatMX(domain)).\n\t\tWhere(\"status = 1\").\n\t\tWhere(\"endtime > ?\", time.Now().Unix()).\n\t\tOrder(\"endtime desc\").\n\t\tLimit(1).\n\t\tScan(&cert)\n\n\tif err != nil {\n\t\treturn certInfo, fmt.Errorf(\"certificate not found in database: %v\", err)\n\t}\n\n\tif cert.Certificate == \"\" {\n\t\treturn certInfo, fmt.Errorf(\"certificate content is empty in database\")\n\t}\n\n\t// Parse certificate information\n\terr = gconv.Struct(acme.GetCertInfo(cert.Certificate), &certInfo)\n\tif err != nil {\n\t\treturn certInfo, fmt.Errorf(\"failed to parse certificate info: %v\", err)\n\t}\n\n\t// Set certificate content\n\tcertInfo.CertPem = cert.Certificate\n\tcertInfo.KeyPem = cert.PrivateKey\n\n\treturn certInfo, nil\n}\n\n// getSSLInfoFromFiles retrieves SSL certificate from file system (legacy method)\nfunc (c *Certificate) getSSLInfoFromFiles(domain string) (certInfo v1.CertInfo, err error) {\n\tcsrPath := filepath.Join(consts.SSL_PATH, domain, \"/fullchain.pem\")\n\tkeyPath := filepath.Join(consts.SSL_PATH, domain, \"/privkey.pem\")\n\n\tif !c.checkCertificateFiles(csrPath, keyPath) {\n\t\treturn certInfo, nil\n\t}\n","sourceCodeStart":501,"sourceCodeEnd":537,"githubUrl":"https://github.com/Billionmail/BillionMail/blob/fc36c76c050c3775c5e899faf7403cf0262d2744/core/internal/service/mail_service/certificate.go#L501-L537","documentation":"The stored PEM is parsed via acme.GetCertInfo and mapped into certInfo with gconv.Struct. If the PEM is malformed, encrypted, not a certificate, or GetCertInfo returns data that can't map onto certInfo, this error is thrown.","triggerScenarios":"GetSSLInfo loads a cert row whose certificate column holds corrupt/truncated PEM, a private key instead of a cert, or an unsupported format that acme.GetCertInfo cannot decode.","commonSituations":"Manual copy-paste of the certificate introduced whitespace/wrong blocks; upload swapped cert and key; certificate file truncated during transfer; PEM with extra non-cert blocks.","solutions":["Validate the stored value is a full PEM cert (-----BEGIN CERTIFICATE----- ... END CERTIFICATE-----) and re-upload if not.","Re-issue the certificate through the standard flow to regenerate clean PEM.","Confirm you didn't store the private key or chain-only content in the certificate column.","Check acme.GetCertInfo output for nil/err before gconv conversion to isolate which half fails."],"exampleFix":"// before\ncertInfo.CertPem = cert.Certificate\n// after\nif !strings.Contains(cert.Certificate, \"BEGIN CERTIFICATE\") {\n    return certInfo, errors.New(\"stored value is not a PEM certificate\")\n}\ncertInfo.CertPem = cert.Certificate","handlingStrategy":"validation","validationCode":"block, _ := pem.Decode([]byte(certPem))\nif block == nil || block.Type != \"CERTIFICATE\" {\n    return errors.New(\"stored certificate is not a valid PEM CERTIFICATE block\")\n}\nif _, err := x509.ParseCertificate(block.Bytes); err != nil {\n    return fmt.Errorf(\"stored certificate does not parse: %w\", err)\n}","typeGuard":"func isValidPEMCert(s string) bool {\n    block, _ := pem.Decode([]byte(s))\n    return block != nil && block.Type == \"CERTIFICATE\"\n}","tryCatchPattern":"info, err := GetSSLInfo(ctx)\nif err != nil {\n    if strings.Contains(err.Error(), \"failed to parse certificate info\") {\n        log.Printf(\"corrupt stored cert: %v — reissuing\", err)\n        return reissueCertificate(ctx)\n    }\n    return err\n}","preventionTips":["Validate PEM with pem.Decode + x509.ParseCertificate before storing.","Never paste certificates manually — upload through the UI which validates format.","Check that cert and key weren't swapped at upload time."],"tags":["ssl","certificate","pem","parsing"],"backgroundTag":"invalid-pem-certificate","analyzedSha":"fc36c76c050c3775c5e899faf7403cf0262d2744","analyzedAt":"2026-09-05T21:28:54.019Z","contentChangedAt":"2026-09-05T21:28:54.019Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}