Billionmail/BillionMail · error

Failed to register user: {}

Error message

Failed to register user: {}

What it means

After challenge setup, the function queries the ACME account with client.Registration.QueryRegistration and, if none exists, registers a new account with client.Registration.Register(TermsOfServiceAgreed:true). This error means new-account registration with the ACME server (Let's Encrypt etc.) failed. Typical lego causes are unreachable ACME directory, rejected terms-of-service URL, invalid account key, or rate limiting.

Source

Thrown at core/internal/service/acme/acme.go:449

		case "godaddy":
			err = SetDnsGodaddy(ctx, client, dnsProviderToken)
			if err != nil {
				return "", "", errors.New(public.LangCtx(ctx, "Failed to set Godaddy DNS verification: {}", err.Error()))
			}
		default:
			return "", "", errors.New(public.LangCtx(ctx, "Unsupported DNS provider: {}", dnsProvider))
		}
	}

	// Register or query existing user on ACME server
	var reg *registration.Resource
	// Try to query existing registration first (same key = same account)
	reg, err = client.Registration.QueryRegistration()
	if err != nil || reg == nil {
		// No existing registration, register new account
		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()))
	}

View on GitHub (pinned to fc36c76c05)

Solutions

  1. Check the wrapped err text and verify the server can reach the ACME directory URL (curl the CAURL endpoint)
  2. Confirm the CAURL setting matches the intended environment (staging vs production) and that the account private key file exists and is valid
  3. Synchronize system time (NTP) and retry; if rate-limited, wait or switch to the staging CA while testing

Example fix

// before
CAURL: "https://acme-v02.api.letsencrypt.org/directory" // unreachable from airgapped host
// after
// open egress to CA, or for testing:
CAURL: lego.LEDirectoryStaging
Defensive patterns

Strategy: retry

Validate before calling

// reachability + time sanity before applying
resp, err := http.Get(caURL + "/directory")
if err != nil || resp.StatusCode != 200 {
    return fmt.Errorf("ACME directory unreachable: %v", err)
}
if time.Now().UTC().Sub(lastNTPCheck) > time.Hour { /* resync clock */ }

Type guard

func acmeUserReady(u *AcmeUser) bool {
    return u != nil && u.Email != "" && u.Registration != nil || (u != nil && u.key != nil)
}

Try / catch

cert, _, err := ApplySSLWithExistingServer(ctx, ...)
if err != nil && strings.Contains(err.Error(), "Failed to register user") {
    // transient CA outages are common: back off and retry
    time.Sleep(30 * time.Second)
    return retryApply(ctx, 3)
}

Prevention

When it happens

Trigger: ApplySSLWithExistingServer (via Apply, StartRenew, ApplyLetsEncryptCertWithHttp, ApplyConsoleCert) when the saved ACME user key has no existing registration and client.Registration.Register fails — e.g. CA endpoint unreachable, CA in downtime, EAB/ToS mismatch, or the account key is corrupt.

Common situations: Server without outbound internet/HTTPS to acme-v02.api.letsencrypt.org; wrong CAURL configured (staging vs production); Let's Encrypt maintenance windows; system clock skew breaking JWS signatures.

Related errors


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