Billionmail/BillionMail · error

invalid certificate

Error message

invalid certificate

What it means

SaveToDatabase parses the issued certificate with GetCertInfo and rejects it when the Subject field comes back empty, meaning the certificate PEM could not be parsed or is empty. This guards against persisting a malformed/blank certificate record. It indicates the certificate string passed in is not a valid PEM certificate.

Source

Thrown at core/internal/service/acme/cli.go:227

	if err != nil {
		return "", "", fmt.Errorf("failed to save private key: %v", err)
	}

	fmt.Printf("Certificate saved to: %s\n", certificatePath)
	fmt.Printf("Private key saved to: %s\n", privateKeyPath)

	return certificatePath, privateKeyPath, nil
}

/**
 * @brief Save certificate to database
 * @return error
 */
func (cli *AcmeCLI) SaveToDatabase(accountId int, certificate, privateKey string) (int, error) {
	// Get certificate info
	certInfo := GetCertInfo(certificate)
	if certInfo.Subject == "" {
		return 0, fmt.Errorf("invalid certificate")
	}

	// Prepare DNS names
	dnsNames, _ := json.Marshal(cli.Domains)

	// Prepare data
	data := map[string]interface{}{
		"account_id":   accountId,
		"certificate":  certificate,
		"private_key":  privateKey,
		"subject":      certInfo.Subject,
		"dns":          string(dnsNames),
		"not_before":   certInfo.NotBefore,
		"not_after":    certInfo.NotAfter,
		"endtime":      certInfo.Endtime,
		"issuer":       certInfo.Issuer,
		"auth_type":    cli.VerifyType,
		"dns_provider": cli.DnsProvider,

View on GitHub (pinned to fc36c76c05)

Solutions

  1. Verify the certificate argument contains actual PEM content (-----BEGIN CERTIFICATE-----) not a file path
  2. Check GetCertInfo against the same certificate to see why Subject is empty
  3. Re-run Apply and confirm the certificate file is non-empty before saving
  4. Validate the certificate with openssl x509 -in cert.pem -noout -subject

Example fix

// before
err := cli.SaveToDatabase(accountId, certPath, keyPath)
// after
certPEM, _ := os.ReadFile(certPath)
if len(certPEM) == 0 { return errors.New("certificate file is empty") }
err := cli.SaveToDatabase(accountId, string(certPEM), keyPEM)
Defensive patterns

Strategy: validation

Validate before calling

certPEM, err := os.ReadFile(certPath)
if err != nil || !bytes.Contains(certPEM, []byte("-----BEGIN CERTIFICATE-----")) {
    return errors.New("certificate PEM missing or malformed")
}
if acme.GetCertInfo(string(certPEM)).Subject == "" {
    return errors.New("certificate not parseable — refusing to save")
}

Prevention

When it happens

Trigger: Calling SaveToDatabase with an empty certificate string, a certificate path instead of PEM content, or PEM that GetCertInfo cannot parse (truncated file, wrong file passed, previous Apply step partially failed).

Common situations: Passing a file path where PEM content is expected; the certificate file was saved empty due to an earlier write error; certificate chain file corrupted during transfer; calling SaveToDatabase before a successful Apply.

Understand the failure class

Related errors


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