Billionmail/BillionMail · error

certificate content is empty in database

Error message

certificate content is empty in database

What it means

After a certificate row is found, getSSLInfoFromDatabase checks cert.Certificate is non-empty. An empty PEM blob means the row exists but the certificate content column was never populated or was cleared, so there is nothing to parse or serve.

Source

Thrown at core/internal/service/mail_service/certificate.go:513

		NotAfter    string `json:"not_after"`
		NotBefore   string `json:"not_before"`
		Dns         string `json:"dns"`
	}

	err = g.DB().Model("letsencrypts").
		Where("dns::jsonb ? $1", public.FormatMX(domain)).
		Where("status = 1").
		Where("endtime > ?", time.Now().Unix()).
		Order("endtime desc").
		Limit(1).
		Scan(&cert)

	if err != nil {
		return certInfo, fmt.Errorf("certificate not found in database: %v", err)
	}

	if cert.Certificate == "" {
		return certInfo, fmt.Errorf("certificate content is empty in database")
	}

	// Parse certificate information
	err = gconv.Struct(acme.GetCertInfo(cert.Certificate), &certInfo)
	if err != nil {
		return certInfo, fmt.Errorf("failed to parse certificate info: %v", err)
	}

	// Set certificate content
	certInfo.CertPem = cert.Certificate
	certInfo.KeyPem = cert.PrivateKey

	return certInfo, nil
}

// getSSLInfoFromFiles retrieves SSL certificate from file system (legacy method)
func (c *Certificate) getSSLInfoFromFiles(domain string) (certInfo v1.CertInfo, err error) {
	csrPath := filepath.Join(consts.SSL_PATH, domain, "/fullchain.pem")

View on GitHub (pinned to fc36c76c05)

Solutions

  1. Re-issue or re-upload the certificate so the certificate column contains valid PEM.
  2. Delete the empty row so the service falls back to a valid certificate or triggers issuance.
  3. Check the issuance pipeline for steps that persist the row before the PEM is available.
  4. Inspect the row directly (SELECT certificate FROM ... ) to confirm emptiness.
Defensive patterns

Strategy: validation

Validate before calling

var pem string
err := g.DB().Model("certificates").Where("endtime > ?", time.Now().Unix()).Order("endtime desc").Limit(1).Value("certificate").Scan(&pem)
if err != nil || !strings.Contains(pem, "BEGIN CERTIFICATE") {
    // row empty or invalid — re-issue before calling GetSSLInfo
}

Try / catch

if err := GetSSLStatus(ctx); err != nil {
    if strings.Contains(err.Error(), "certificate content is empty") {
        return reissueCertificate(ctx)
    }
    return err
}

Prevention

When it happens

Trigger: GetSSLInfo reads a DB row where the certificate column is '' — e.g. a record created by a failed issuance, manual row insertion, or a wiped/placeholder row.

Common situations: Issuance job crashed after inserting the row but before writing PEM content; admin deleted cert content while debugging; backup/restore truncated large text columns.

Understand the failure class

Related errors


AI-assisted analysis of Billionmail/BillionMail@fc36c76c05 (2026-09-05). Data as JSON: /api/errors/64351fb3e90c6220. Report an issue: GitHub.