Billionmail/BillionMail · error

Failed to get configuration

Error message

Failed to get configuration

What it means

ApplySSLWithExistingServer builds the lego ACME configuration via GetConfig(myUser), which wraps lego.NewConfig. In this codebase GetConfig is non-nil in normal operation (it always returns lego.NewConfig(...)), so a nil result means the configuration could not be produced at all — the defensive guard fails the certificate application before any ACME traffic happens.

Source

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

 */
func ApplySSLWithExistingServer(ctx context.Context, domains []string, email string, vtype string,
	dnsProvider string, dnsProviderToken map[string]string, savePath string) (string, string, error) {

	// Set up logging
	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 {

View on GitHub (pinned to fc36c76c05)

Solutions

  1. Inspect GetConfig (acme.go:110) for any early `return nil` path and log which condition hit.
  2. Ensure myUser from GetMyUser is fully initialized (email + private key) before calling GetConfig.
  3. Confirm the ACME directory URL configuration (CA env or default) is set so GetConfig doesn't bail.
  4. If GetConfig cannot fail in your version, treat this as dead defensive code and log the caller context for diagnosis.

Example fix

// before
config := GetConfig(myUser)
if config == nil {
    return "", "", errors.New("Failed to get configuration")
}
// after
if myUser == nil || myUser.GetPrivateKey() == nil {
    return "", "", errors.New("ACME user not initialized")
}
config := GetConfig(myUser)
Defensive patterns

Strategy: validation

Validate before calling

if myUser == nil || myUser.GetEmail() == "" || myUser.GetPrivateKey() == nil {
    return errors.New("ACME user not initialized: email and private key are required")
}
config := GetConfig(myUser)

Type guard

func acmeUserReady(u *MyUser) bool {
    return u != nil && u.GetEmail() != "" && u.GetPrivateKey() != nil
}

Try / catch

config := GetConfig(myUser)
if config == nil {
    log.Printf("GetConfig returned nil for user %s — inspect GetConfig early-return paths", myUser.GetEmail())
    return "", "", errors.New("failed to build ACME configuration")
}

Prevention

When it happens

Trigger: Any caller (Apply, StartRenew, ApplyLetsEncryptCertWithHttp, ApplyConsoleCert) reaching ApplySSLWithExistingServer where GetConfig(myUser) returns nil — e.g. after code changes that make GetConfig bail out early, or if myUser initialization paths change so the config construction is skipped.

Common situations: A refactor of GetConfig that added an early return; a nil/uninitialized MyUser with no private key causing a guarded early return; an environment (CA URL not set / CA_DIRECTORY env empty) that a modified GetConfig treats as fatal and returns nil for.

Related errors


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