Billionmail/BillionMail · error
Failed to create ACME client: {}
Error message
Failed to create ACME client: {} What it means
lego.NewClient(config) failed while constructing the ACME client from the previously obtained *lego.Config. lego errors here when the config's private key is invalid or the user registration data is unusable — it cannot assemble a client without a workable key. The code wraps the library error with a localized message.
Source
Thrown at core/internal/service/acme/acme.go:392
logFile := GetLogFile(ctx)
SetLog(logFile)
defer CloseLog(logFile)
// Get user information
myUser, err := GetMyUser(ctx, email)
if err != nil {
return "", "", err
}
// Get configuration
config := GetConfig(myUser)
if config == nil {
return "", "", errors.New(public.LangCtx(ctx, "Failed to get configuration"))
}
client, err := lego.NewClient(config)
if err != nil {
return "", "", errors.New(public.LangCtx(ctx, "Failed to create ACME client: {}", err.Error()))
}
// Set verification method
if vtype == "http" {
// Assume the HTTP server is already running and properly configured
// to handle the challenge requests
err = client.Challenge.SetHTTP01Provider(http01.NewProviderServer("127.0.0.1", "60880"))
if err != nil {
return "", "", errors.New(public.LangCtx(ctx, "Failed to set HTTP verification: {}", err.Error()))
}
} else if vtype == "dns" && dnsProvider != "" {
// Set DNS verification - same as in the standard ApplySSL function
switch dnsProvider {
case "tencentcloud":
err = SetDnsTencentcloud(ctx, client, dnsProviderToken)
if err != nil {
return "", "", errors.New(public.LangCtx(ctx, "Failed to set Tencent Cloud DNS verification: {}", err.Error()))
}View on GitHub (pinned to fc36c76c05)
Solutions
- Read the wrapped err.Error() — lego states whether the key is nil, malformed, or unsupported.
- Regenerate the ACME account key (ECDSA P-256 or RSA 2048+) and re-register the account.
- Verify the stored key file/record loads and parses (pem.Decode / x509.ParseECPrivateKey) before calling ApplySSLWithExistingServer.
- Restore the account key from backup if it was corrupted in storage.
Example fix
// before
myUser.key = loadRawKeyBytes() // raw bytes, not parsed
client, err := lego.NewClient(config)
// after
key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
if err != nil {
return "", "", err
}
myUser.key = key
client, err := lego.NewClient(config) Defensive patterns
Strategy: try-catch
Validate before calling
func accountKeyValid(key crypto.PrivateKey) error {
switch k := key.(type) {
case *ecdsa.PrivateKey:
return k.Validate()
case *rsa.PrivateKey:
return k.Validate()
default:
return fmt.Errorf("unsupported account key type %T", key)
}
} Type guard
func usableAccountKey(u *MyUser) bool {
switch u.GetPrivateKey().(type) {
case *ecdsa.PrivateKey, *rsa.PrivateKey:
return true
default:
return false
}
} Try / catch
client, err := lego.NewClient(config)
if err != nil {
log.Printf("lego.NewClient failed: %v — regenerating account key", err)
if regErr := reRegisterAcmeAccount(ctx, email); regErr != nil {
return "", "", regErr
}
return "", "", errors.New("ACME client rebuilt with new account key; retry")
} Prevention
- Persist the ACME account key with correct file permissions and verify it parses on load.
- Generate keys with ecdsa P-256 (lego's default) — avoid exotic algorithms.
- On NewClient failure, regenerate the key and re-register instead of failing permanently.
- Back up the ACME account record so a corrupted key can be restored.
When it happens
Trigger: Any ApplySSLWithExistingServer caller where the MyUser's private key is nil, corrupt, or of an unsupported type, so lego.NewClient rejects it during client construction.
Common situations: A persisted ACME account key file that was truncated/corrupted by disk issues; keys generated with unsupported algorithms or wrong PEM encoding; a user record deserialized from storage missing the key field; refactors that changed how the key is stored/loaded.
Related errors
- Failed to get configuration
- DNS verification setup failed: {}
- DNS automated resolution failed: ClientID, ClientSecret or T
- DNS automated resolution failed: APIKey or APISecret is empt
- Failed to set HTTP verification: {}
AI-assisted analysis of Billionmail/BillionMail@fc36c76c05 (2026-09-05).
Data as JSON: /api/errors/200b07e1c96a2332.
Report an issue: GitHub.