caddyserver/caddy · warning · PublishECHConfigListErrors
unable to publish ECH data to HTTPS DNS record: %w (zone=%s
Error message
unable to publish ECH data to HTTPS DNS record: %w (zone=%s dns_record_name=%s)
What it means
The final write of ECH DNS publishing: dnsPub.provider.SetRecords sets the HTTPS ServiceBinding record (priority 2, target '.', TTL 5m, ech SvcParam merged with existing params). Failure is wrapped with zone and record name context and collected into PublishECHConfigListErrors for that domain. Causes are provider-side: auth, permissions, zone mismatch, rate limits, or API errors.
Source
Thrown at modules/caddytls/ech.go:895
continue
}
params := httpsRec.Params
params = dnsPub.publishedSvcParams(domain, params, configListBin)
// publish record
_, err = dnsPub.provider.SetRecords(ctx, zone, []libdns.Record{
libdns.ServiceBinding{
// HTTPS and SVCB RRs: RFC 9460 (https://www.rfc-editor.org/rfc/rfc9460)
Scheme: "https",
Name: relName,
TTL: 5 * time.Minute, // TODO: low hard-coded value only temporary; change to a higher value once more field-tested and key rotation is implemented
Priority: 2, // allows a manual override with priority 1
Target: ".",
Params: params,
},
})
if err != nil {
errs[domain] = fmt.Errorf("unable to publish ECH data to HTTPS DNS record: %w (zone=%s dns_record_name=%s)", err, zone, relName)
continue
}
}
if len(errs) > 0 {
return errs
}
return nil
}
func (dnsPub *ECHDNSPublisher) publishedSvcParams(domain string, existing libdns.SvcParams, configListBin []byte) libdns.SvcParams {
params := make(libdns.SvcParams, len(existing)+2)
for key, values := range existing {
params[key] = append([]string(nil), values...)
}
params["ech"] = []string{base64.StdEncoding.EncodeToString(configListBin)}
View on GitHub (pinned to 50e54ee279)
Solutions
- Use the zone= and dns_record_name= in the message plus the wrapped error to pinpoint the rejected write.
- Grant the token write access for that zone (or move DNS hosting to the configured provider).
- Retry after rate-limit windows; spread publications if many domains.
- Verify manually that the API token can create HTTPS/SVCB records via the provider's console.
Defensive patterns
Strategy: retry
Try / catch
var perrs caddytls.PublishECHConfigListErrors
if errors.As(err, &perrs) {
for d, e := range perrs {
if strings.Contains(e.Error(), "unable to publish ECH data") {
// zone/record named in message; fix token write scope or zone hosting, then reload
}
}
} Prevention
- Verify the account/token actually manages the DNS zone of each ECH name.
- Test one HTTPS record write via the provider API before wide rollout.
- Expect retries: ECH republish happens on maintenance intervals, so transient API errors self-heal.
When it happens
Trigger: SetRecords for <relName> HTTPS RR in <zone> rejected: token lacks write scope, zone not managed by that provider account, provider API 4xx/5xx, concurrent modification conflict.
Common situations: Read-only DNS token; domain's DNS hosted at a different provider than configured; publishing during a provider outage; very long record sets exceeding provider limits.
Related errors
- unable to get existing DNS records to publish ECH data to HT
- loading ECH DNS provider module: %v
- ECH DNS provider module is not an ECH DNS Provider: %v
- could not determine zone for domain: %w (domain=%s nameserve
- public name length (%d) must be in the range 1-255
AI-assisted analysis of caddyserver/caddy@50e54ee279 (2026-08-15).
Data as JSON: /api/errors/a568106497039137.
Report an issue: GitHub.