Billionmail/BillionMail · error
fail to set ssl: %w
Error message
fail to set ssl: %w
What it means
SetSSL wraps any error from crt.SetSNI(public.FormatMX(req.Domain), req.Certificate, req.Key) with this message. SetSNI installs the certificate/key pair as an SNI entry for the mail hostname (mail.example.com) in the mail server config, so failures mean the cert could not be written or applied.
Source
Thrown at core/internal/controller/domains/domains_v1_set_ssl.go:34
if ex, err1 := domains.Exists(ctx, req.Domain); !ex {
if err1 != nil {
res.SetError(fmt.Errorf("fail to check domain: %w", err1))
return
}
res.SetError(fmt.Errorf("domain %s does not exist", req.Domain))
return
}
crt := mail_service.NewCertificate()
defer crt.Close()
err = crt.SetSNI(public.FormatMX(req.Domain), req.Certificate, req.Key)
if err != nil {
res.SetError(fmt.Errorf("fail to set ssl: %w", err))
return
}
_ = public.WriteLog(ctx, public.LogParams{
Type: consts.LOGTYPE.Domain,
Log: "Set SSL for domain :" + req.Domain + " successfully",
Data: req,
})
res.SetSuccess(public.LangCtx(ctx, "Success"))
return
}
View on GitHub (pinned to fc36c76c05)
Solutions
- Validate that req.Key is the private key corresponding to req.Certificate (compare modulus/pubkey) and both are valid PEM.
- Ensure the full chain (leaf + intermediates) is included and markers/line endings are intact.
- Inspect the wrapped inner error (%w) for the exact SetSNI failure and fix filesystem/permission issues it reports.
- Restart the mail service if config was partially written, then retry.
Example fix
// before
{"certificate":"-----BEGIN CERTIFICATE-----\nMIIB...", "key":"<ssh key by mistake>"}
// after
{"certificate":"-----BEGIN CERTIFICATE-----\n...CHAIN...\n-----END CERTIFICATE-----", "key":"-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----"} Defensive patterns
Strategy: validation
Validate before calling
// Pre-flight: match cert and key, and check PEM markers
certPub := extractPubKey(certPEM)
keyPub := extractPubKey(keyPEM)
if !bytes.Equal(certPub, keyPub) {
return errors.New("certificate and private key do not match")
}
if !strings.Contains(certPEM, "BEGIN CERTIFICATE") || !strings.Contains(keyPEM, "BEGIN") {
return errors.New("invalid PEM content")
} Try / catch
if err := setSSL(domain, cert, key); err != nil {
var inner error
errors.As(err, &inner) // message is 'fail to set ssl: %w'; log the unwrapped cause
return fmt.Errorf("SSL install failed: %v", inner)
} Prevention
- Always upload matching cert/key pairs generated together.
- Include the full chain and use BEGIN/END PEM markers with LF line endings.
- Ensure the cert store directory is writable by the service user in your deployment.
When it happens
Trigger: Passing an invalid PEM certificate or mismatched private key in req.Certificate/req.Key; empty cert/key fields; SetSNI failing to update the underlying mail service config; file permission problems writing the cert store.
Common situations: Uploading a cert whose key does not match; cert chain in wrong order; pasting a cert with Windows line endings or missing BEGIN/END markers; container lacking write access to the cert directory; Docker volume not mounted.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- Failed to create directory: {}
- Failed to save certificate file: {}
- certificate not found in database: %v
- certificate content is empty in database
- failed to parse certificate info: %v
AI-assisted analysis of Billionmail/BillionMail@fc36c76c05 (2026-09-05).
Data as JSON: /api/errors/d0b35cdb7c0e6c66.
Report an issue: GitHub.