Billionmail/BillionMail · error
Failed to apply for SSL certificate: {}
Error message
Failed to apply for SSL certificate: {} What it means
The final ACME step calls client.Certificate.Obtain(request) to run the chosen challenge and fetch the certificate. This error wraps every failure lego reports during that flow — challenge validation failures (HTTP-01 on 127.0.0.1:60880 unreachable by the CA, or DNS-01 TXT record wrong/propagating), authorization failures, and CA-side rate limits. The wrapped err text names the exact failing domain and challenge type.
Source
Thrown at core/internal/service/acme/acme.go:465
reg, err = client.Registration.Register(registration.RegisterOptions{TermsOfServiceAgreed: true})
if err != nil {
return "", "", errors.New(public.LangCtx(ctx, "Failed to register user: {}", err.Error()))
}
}
// Save user information
myUser.Registration = reg
// Submit application
request := certificate.ObtainRequest{
Domains: domains,
Bundle: true,
}
// Get certificate
certificates, err := client.Certificate.Obtain(request)
if err != nil {
return "", "", errors.New(public.LangCtx(ctx, "Failed to apply for SSL certificate: {}", err.Error()))
}
// Save certificate files if path is provided
if savePath != "" {
// Create directory if it doesn't exist
if !public.FileExists(savePath) {
err = os.MkdirAll(savePath, 0750)
if err != nil {
return "", "", errors.New(public.LangCtx(ctx, "Failed to create directory: {}", err.Error()))
}
}
// Save certificate and private key files
certificateFile := filepath.Join(savePath, "certificate.pem")
privateKeyFile := filepath.Join(savePath, "private_key.pem")
_, err = public.WriteFile(certificateFile, string(certificates.Certificate))
if err != nil {View on GitHub (pinned to fc36c76c05)
Solutions
- Read the wrapped err to identify the failing domain/challenge; for http-01 verify the CA can reach the domain on port 80 and that traffic reaches the challenge server on 127.0.0.1:60880 (open/forward port 80, disable blocking proxy rules)
- For dns-01, confirm the DNS provider token works and the TXT record appears (_acme-challenge.<domain>) via dig before retrying
- Wait out rate limits or use the Let's Encrypt staging CA while debugging, then retry with production
Example fix
// before // port 80 closed; CA cannot reach challenge // after // open port 80 in firewall/NAT so http://<domain>/.well-known/acme-challenge/ reaches 127.0.0.1:60880
Defensive patterns
Strategy: retry
Validate before calling
// pre-flight: port 80 reachable and DNS points here (http-01)
if vtype == "http" {
ip, _ := net.LookupIP(domain)
pub, _ := externalIP()
if len(ip) == 0 || ip[0].String() != pub { return errors.New("domain does not resolve to this server") }
}
// dns-01: check TXT after provider setup
// dig TXT _acme-challenge.<domain> +short Type guard
func challengeReachable(vtype, domain string) bool {
if vtype == "http" {
conn, err := net.DialTimeout("tcp", domain+":80", 5*time.Second)
if err != nil { return false }
conn.Close()
}
return true
} Try / catch
cert, _, err := ApplySSLWithExistingServer(ctx, ...)
if err != nil && strings.Contains(err.Error(), "Failed to apply for SSL certificate") {
// challenge failures are often transient (propagation, rate limits)
time.Sleep(1 * time.Minute)
return retryApplyWithBackoff(ctx, 3)
} Prevention
- Ensure port 80 is open/forwarded to the challenge server for http-01
- Verify TXT record propagation before retrying dns-01
- Use the staging CA while debugging to avoid rate limits
- Confirm the domain's DNS A record points at the machine running this code
When it happens
Trigger: ApplySSLWithExistingServer (via Apply, StartRenew, ApplyLetsEncryptCertWithHttp, ApplyConsoleCert) where the CA cannot validate the challenge: for http-01, the CA cannot reach http://<domain>/.well-known/acme-challenge (port 80 closed or not forwarded to 127.0.0.1:60880); for dns-01, the TXT record was not created/propagated or credentials lack zone write access.
Common situations: Firewall/NAT blocking port 80 in front of the challenge server; domain's DNS pointing elsewhere than the server running this code; DNS propagation delay; Let's Encrypt rate limits after repeated failures; expired wildcard attempts using dns provider with wrong zone.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- DNS verification setup failed: {}
- Failed to set HTTP verification: {}
- Failed to register user: {}
- fail to check domain: %w
- domain %s does not exist
AI-assisted analysis of Billionmail/BillionMail@fc36c76c05 (2026-09-05).
Data as JSON: /api/errors/9b16252bf1959b98.
Report an issue: GitHub.