caddyserver/caddy · error
URL is required
Error message
URL is required
What it means
Returned by HTTPCertGetter.Provision (the tls.get_certificate.http module, i.e. 'get_certificate http <url>' in a Caddyfile) when the URL field is empty. The module fetches a certificate bundle over HTTP at handshake time, so an endpoint is mandatory; provisioning fails fast rather than letting every handshake fail later.
Source
Thrown at modules/caddytls/certmanagers.go:124
// (No Content). Error statuses will indicate that the manager is
// capable of providing a certificate but was unable to.
URL string `json:"url,omitempty"`
ctx context.Context
}
// CaddyModule returns the Caddy module information.
func (hcg HTTPCertGetter) CaddyModule() caddy.ModuleInfo {
return caddy.ModuleInfo{
ID: "tls.get_certificate.http",
New: func() caddy.Module { return new(HTTPCertGetter) },
}
}
func (hcg *HTTPCertGetter) Provision(ctx caddy.Context) error {
hcg.ctx = ctx
if hcg.URL == "" {
return fmt.Errorf("URL is required")
}
return nil
}
func (hcg HTTPCertGetter) GetCertificate(ctx context.Context, hello *tls.ClientHelloInfo) (*tls.Certificate, error) {
sigs := make([]string, len(hello.SignatureSchemes))
for i, sig := range hello.SignatureSchemes {
sigs[i] = fmt.Sprintf("%x", uint16(sig)) // you won't believe what %x uses if the val is a Stringer
}
suites := make([]string, len(hello.CipherSuites))
for i, cs := range hello.CipherSuites {
suites[i] = fmt.Sprintf("%x", cs)
}
parsed, err := url.Parse(hcg.URL)
if err != nil {
return nil, err
}View on GitHub (pinned to 50e54ee279)
Solutions
- Add the URL: 'get_certificate http https://certs.example.com/certs' in the Caddyfile
- If using JSON, ensure the module object has a non-empty "url" value
- Run 'caddy adapt --config Caddyfile --adapter caddyfile' to confirm the URL survives adaptation
- Check for typos that make the URL parse as a block instead of an argument
Example fix
# before get_certificate http # after get_certificate http https://certs.example.com/certs
Defensive patterns
Strategy: validation
Validate before calling
# Adapt + inspect before running: caddy adapt --config Caddyfile --adapter caddyfile 2>/dev/null | jq '.apps.tls.certificates.get_certificate // empty'
Prevention
- Treat get_certificate http as requiring exactly one argument; add a config lint step that rejects the directive with no URL
- Use 'caddy validate --config <file>' in CI for every config change
- If generating configs programmatically, fail the generator when the URL variable is empty
When it happens
Trigger: Configuring get_certificate http with no URL argument, or JSON config where tls.get_certificate.http has an empty/missing "url" key. In Caddyfile syntax: 'get_certificate http' with the URL line missing or mistyped as a subdirective.
Common situations: Hand-written Caddyfile omits the URL; JSON config built programmatically leaves the field empty; a template/automation pipeline that was supposed to inject the URL produced an empty string.
Related errors
- got HTTP %d
- no certificates matched custom selection policy
- server listening on %v is HTTP, but attempts to configure TL
- two policies with same match criteria have conflicting cert
- finalizing automatic HTTPS: %v
AI-assisted analysis of caddyserver/caddy@50e54ee279 (2026-08-15).
Data as JSON: /api/errors/6d85210de70bf2f9.
Report an issue: GitHub.