Billionmail/BillionMail · error
DNS automated resolution failed: ClientID, ClientSecret or T
Error message
DNS automated resolution failed: ClientID, ClientSecret or TenantID is empty in AzureDNS configuration file
What it means
SetDnsAzuredns pre-validates its keyConfig map before touching the lego Azure DNS provider. If keyConfig is nil or any of ClientID, ClientSecret, or TenantID is an empty string, it fails fast because azuredns.NewDNSProviderConfig cannot authenticate to Azure without all three (a service-principal credential set).
Source
Thrown at core/internal/service/acme/acme.go:242
}
err = client.Challenge.SetDNS01Provider(p)
if err != nil {
return errors.New(public.LangCtx(ctx, "DNS verification setup failed: {}", err.Error()))
}
return nil
}
/**
* @description: Configure DNS verification via Azure DNS
* @param {*lego.Client} client Client
* @param {map[string]string} keyConfig Configuration information
* @return error Error information
*/
func SetDnsAzuredns(ctx context.Context, client *lego.Client, keyConfig map[string]string) error {
if keyConfig == nil || keyConfig["ClientID"] == "" || keyConfig["ClientSecret"] == "" || keyConfig["TenantID"] == "" {
return errors.New(public.LangCtx(ctx, "DNS automated resolution failed: ClientID, ClientSecret or TenantID is empty in AzureDNS configuration file"))
}
cfg := azuredns.NewDefaultConfig()
cfg.ClientID = keyConfig["ClientID"]
cfg.ClientSecret = keyConfig["ClientSecret"]
cfg.TenantID = keyConfig["TenantID"]
p, err := azuredns.NewDNSProviderConfig(cfg)
if err != nil {
return errors.New(public.LangCtx(ctx, "DNS provider initialization failed: {}", err.Error()))
}
err = client.Challenge.SetDNS01Provider(p)
if err != nil {
return errors.New(public.LangCtx(ctx, "DNS verification setup failed: {}", err.Error()))
}
return nilView on GitHub (pinned to fc36c76c05)
Solutions
- Set ClientID, ClientSecret, and TenantID to a valid Azure App Registration (service principal) with DNS Zone Contributor rights on the zone.
- Check that the config file/JSON keys are named exactly ClientID, ClientSecret, TenantID (case-sensitive map lookups).
- Verify the secret is the App Registration client secret, not a certificate or connection string.
- If unsure, use the Azure portal: Entra ID → App registrations → copy Application (client) ID, Directory (tenant) ID, and create a new client secret.
Example fix
// before
keyConfig := map[string]string{"ClientID": id, "ClientSecret": secret} // TenantID missing
err := SetDnsAzuredns(ctx, client, keyConfig)
// after
keyConfig := map[string]string{"ClientID": id, "ClientSecret": secret, "TenantID": tenantID}
err := SetDnsAzuredns(ctx, client, keyConfig) Defensive patterns
Strategy: validation
Validate before calling
func azureDNSConfigReady(kc map[string]string) bool {
if kc == nil {
return false
}
guid := regexp.MustCompile(`^[0-9a-fA-F-]{36}$`)
return kc["ClientSecret"] != "" && guid.MatchString(kc["ClientID"]) && guid.MatchString(kc["TenantID"])
} Type guard
func hasAzureDNSKeys(kc map[string]string) bool {
for _, k := range []string{"ClientID", "ClientSecret", "TenantID"} {
if kc == nil || strings.TrimSpace(kc[k]) == "" {
return false
}
}
return true
} Try / catch
if err := SetDnsAzuredns(ctx, client, tokens); err != nil {
if strings.Contains(err.Error(), "TenantID") {
return fmt.Errorf("Azure service principal incomplete: %w", err)
}
return err
} Prevention
- Collect all three service-principal fields (ClientID, ClientSecret, TenantID) as required inputs in the UI.
- Validate GUID format for ClientID/TenantID before submission.
- Name config keys exactly as the map lookups expect (case-sensitive).
- Grant the service principal DNS Zone Contributor role on the target zone at setup time.
When it happens
Trigger: ApplySSLWithExistingServer with vtype="dns" and dnsProvider="azuredns" where the token map lacks ClientID, ClientSecret, or TenantID, or is entirely nil.
Common situations: Users supply an Azure connection string or subscription ID instead of a service principal; only two of the three fields were entered in the UI; the tenant ID was omitted because it was confused with the subscription ID; the config file failed to parse so the map is nil.
Understand the failure class
Background: "environment variable is not set" and "Missing keys in environment" errors: what missing required env var messages mean and how to fix them — this error's family across 28 libraries.
Related errors
- DNS automated resolution failed: APIKey or APISecret is empt
- DNS automated resolution failed: SecretId or SecretKey is em
- DNS automated resolution failed: APIKey or SecretKey is empt
- DNS automated resolution failed: APIKey or Email is empty in
- DNS automated resolution failed: APIKey or SecretKey is empt
AI-assisted analysis of Billionmail/BillionMail@fc36c76c05 (2026-09-05).
Data as JSON: /api/errors/78369ff10ffe8bd1.
Report an issue: GitHub.