caddyserver/caddy · error

filling in global issuer defaults for AP %d, issuer %d: %v

Error message

filling in global issuer defaults for AP %d, issuer %d: %v

What it means

During TLS app finalization, each automation policy's issuers get global ACME defaults filled in (fillInGlobalACMEDefaults: email, acme_ca, acme_ca_root, acme_dns, acme_eab, preferred_chains, ...). Inspecting fillInGlobalACMEDefaults shows its only failing path is the acme_dns-without-provider check, so this wrapper ('for AP %d, issuer %d') almost always wraps exactly that error, with the policy and issuer indexes telling you which entry triggered it.

Source

Thrown at caddyconfig/httpcaddyfile/tlsapp.go:473

					ap.Issuers = caddytls.DefaultIssuers(emailStr)

					// if a specific endpoint is configured, can't use multiple default issuers
					if globalACMECA != nil {
						ap.Issuers = []certmagic.Issuer{new(caddytls.ACMEIssuer)}
					}
				}
			}
		}
	}

	// finalize and verify policies; do cleanup
	if tlsApp.Automation != nil {
		for i, ap := range tlsApp.Automation.Policies {
			// ensure all issuers have global defaults filled in
			for j, issuer := range ap.Issuers {
				err := fillInGlobalACMEDefaults(issuer, options)
				if err != nil {
					return nil, warnings, fmt.Errorf("filling in global issuer defaults for AP %d, issuer %d: %v", i, j, err)
				}
			}

			// encode all issuer values we created, so they will be rendered in the output
			if len(ap.Issuers) > 0 && ap.IssuersRaw == nil {
				for _, iss := range ap.Issuers {
					issuerName := iss.(caddy.Module).CaddyModule().ID.Name()
					ap.IssuersRaw = append(ap.IssuersRaw, caddyconfig.JSONModuleObject(iss, "module", issuerName, &warnings))
				}
			}
		}

		// consolidate automation policies that are the exact same
		tlsApp.Automation.Policies = consolidateAutomationPolicies(tlsApp.Automation.Policies)

		// ensure automation policies don't overlap subjects (this should be
		// an error at provision-time as well, but catch it in the adapt phase
		// for convenience)

View on GitHub (pinned to 50e54ee279)

Solutions

  1. Read the trailing '%v' of the message — it carries the underlying fillInGlobalACMEDefaults error (in practice: the acme_dns/DNS-provider error).
  2. Give 'acme_dns' a provider (e.g. 'acme_dns cloudflare {env.CF_API_TOKEN}') or add a global 'dns' provider so bare acme_dns can inherit it.
  3. Scope DNS challenge config to the specific site's tls block instead of globally.
  4. Run 'caddy adapt' / 'caddy validate' to iterate quickly.

Example fix

# before
{
  acme_dns
}

# after
{
  acme_dns cloudflare {env.CF_API_TOKEN}
}
Defensive patterns

Strategy: validation

Validate before calling

caddy validate --config Caddyfile --adapter caddyfile  # surfaces the wrapped fillInGlobalACMEDefaults error

Prevention

When it happens

Trigger: An ACME-capable issuer in policy i whose DNS challenge has no provider while global 'acme_dns' was specified bare (nil) and no global 'dns' option exists; the indexes identify which policy/issuer combination hit it.

Common situations: Setting bare 'acme_dns' globally while per-site tls blocks create their own ACME issuers; migrating from per-site dns challenge config to global options incompletely.

Related errors


AI-assisted analysis of caddyserver/caddy@50e54ee279 (2026-08-15). Data as JSON: /api/errors/53b7f9e70514e057. Report an issue: GitHub.