caddyserver/caddy · error
provisioning automation policy %d: %v
Error message
provisioning automation policy %d: %v
What it means
Each user-defined policy in tls.automation.policies is provisioned in order; this error wraps the failure of policy at index %d. The wrapped message comes from AutomationPolicy.Provision (automation.go:182) and can be: subject punycode/IDNA conversion failure, storage module load failure, external certificate manager (ManagersRaw) load failure, issuer module load failure, or default issuer provisioning failure.
Source
Thrown at modules/caddytls/tls.go:317
// if any names specified by the "automate" loader do not qualify for a public
// certificate, we should initialize a default internal automation policy
// (but we don't want to do this unnecessarily, since it may prompt for password!)
if certmagic.SubjectQualifiesForPublicCert(n) {
continue
}
t.Automation.defaultInternalAutomationPolicy = &AutomationPolicy{
IssuersRaw: []json.RawMessage{json.RawMessage(`{"module":"internal"}`)},
}
err = t.Automation.defaultInternalAutomationPolicy.Provision(t)
if err != nil {
return fmt.Errorf("provisioning default internal automation policy: %v", err)
}
break
}
for i, ap := range t.Automation.Policies {
err := ap.Provision(t)
if err != nil {
return fmt.Errorf("provisioning automation policy %d: %v", i, err)
}
}
// run replacer on ask URL (for environment variables) -- return errors to prevent surprises (#5036)
if t.Automation != nil && t.Automation.OnDemand != nil && t.Automation.OnDemand.Ask != "" {
t.Automation.OnDemand.Ask, err = repl.ReplaceOrErr(t.Automation.OnDemand.Ask, true, true)
if err != nil {
return fmt.Errorf("preparing 'ask' endpoint: %v", err)
}
perm := PermissionByHTTP{
Endpoint: t.Automation.OnDemand.Ask,
}
if err := perm.Provision(ctx); err != nil {
return fmt.Errorf("provisioning 'ask' module: %v", err)
}
t.Automation.OnDemand.permission = perm
}
View on GitHub (pinned to 50e54ee279)
Solutions
- The wrapped error names the exact sub-failure; fix that first (it is usually more specific than this message)
- The index %d refers to the position in automation.policies — count from 0 to find the offending policy
- Validate subjects are legal DNS names (use punycode for unicode, avoid underscores)
- Run 'caddy validate' — provisioning errors surface at validation time, before Start
Example fix
// before
{"policies": [{"subjects": ["exa_mple.com"], "issuers": [{"module": "acme"}]}]}
// after
{"policies": [{"subjects": ["example.com"], "issuers": [{"module": "acme"}]}]} Defensive patterns
Strategy: validation
Validate before calling
import "github.com/miekg/dns"
func validSubject(s string) bool {
_, ok := dns.IsDomainName(s)
return ok && !strings.Contains(s, "_")
} Prevention
- Use the policy index in the message to locate the failing entry (0-based)
- Prefer 'caddy validate' — provisioning runs during validation and reports errors before Start
- Convert unicode domains to punycode and avoid underscores in subjects
When it happens
Trigger: A subject like 'exa_mple.com' or invalid unicode that fails idna.ToASCII; an issuers entry with a bad module name or invalid fields (e.g. acme issuer with malformed ca URL); a managers entry whose plugin is not compiled in; policy storage module misconfiguration.
Common situations: Hand-written policy subjects with underscores or wildcards in the wrong position; typo'd issuer modules; plugin version drift after Caddy upgrades; DN-ish names or non-DNS strings in subjects.
Related errors
- provisioning default public automation policy: %v
- automation policy %d is the second policy that acts as defau
- loading new config: %v
- loading storage module: %v
- consolidating TLS connection policies for server %d: %v
AI-assisted analysis of caddyserver/caddy@50e54ee279 (2026-08-15).
Data as JSON: /api/errors/f9f3438bb334af6b.
Report an issue: GitHub.