caddyserver/caddy · error
unsupported HTTP version: %s, supported version: %s
Error message
unsupported HTTP version: %s, supported version: %s
What it means
The HTTP transport's `versions` list is validated against `allowedVersions` (`"1.1"`, `"2"`, `"3"`). Any other string fails provisioning immediately (per issue #7111, Caddy errors instead of guessing), with the supported list included in the message.
Source
Thrown at modules/caddyhttp/reverseproxy/httptransport.go:193
}
var (
allowedVersions = []string{"1.1", "2", "h2c", "3"}
allowedVersionsString = strings.Join(allowedVersions, ", ")
)
// Provision sets up h.Transport with a *http.Transport
// that is ready to use.
func (h *HTTPTransport) Provision(ctx caddy.Context) error {
if len(h.Versions) == 0 {
h.Versions = []string{"1.1", "2"}
}
// some users may provide http versions not recognized by caddy, instead of trying to
// guess the version, we just error out and let the user fix their config
// see: https://github.com/caddyserver/caddy/issues/7111
for _, v := range h.Versions {
if !slices.Contains(allowedVersions, v) {
return fmt.Errorf("unsupported HTTP version: %s, supported version: %s", v, allowedVersionsString)
}
}
rt, err := h.NewTransport(ctx)
if err != nil {
return err
}
h.Transport = rt
return nil
}
// NewTransport builds a standard-lib-compatible http.Transport value from h.
func (h *HTTPTransport) NewTransport(caddyCtx caddy.Context) (*http.Transport, error) {
// Set keep-alive defaults if it wasn't otherwise configured
if h.KeepAlive == nil {
h.KeepAlive = new(KeepAlive)
}View on GitHub (pinned to 50e54ee279)
Solutions
- Use only the exact strings from the message: "1.1", "2", "3"
- Replace bare "1" or "1.0" with "1.1"
- Remove multiple values if you intended a single version: versions 3 forces HTTP/3-only
Example fix
# before
reverse_proxy localhost:9000 {
transport http {
versions 2.0 1
}
}
# after
reverse_proxy localhost:9000 {
transport http {
versions 1.1 2
}
} Defensive patterns
Strategy: validation
Validate before calling
var allowedVersions = map[string]bool{"1.1": true, "2": true, "3": true}
for _, v := range h.Versions {
if !allowedVersions[v] {
return fmt.Errorf("bad version %q; want 1.1, 2 or 3", v)
}
} Prevention
- Copy the literal allowed values from the error message into config templates
- Note there is no "1" or "2.0" — exact strings only
When it happens
Trigger: Setting `transport http { versions 2.0 }`, `versions h2c`, `versions HTTP/2`, or `versions 1 2` (bare "1" is not valid — it is "1.1"). In JSON, the Transport versions array containing any non-allowed value.
Common situations: Assuming nginx-style version tokens (http2, 1.0), typos like `verions`, or copying config between Caddy versions without checking the directive's allowed values.
Related errors
- local_address must be a single address, not a port range
- local_address must be a TCP address, not a UDP address
- unsupported network
- failed to load network_proxy module: %v
- making TLS client config: %v
AI-assisted analysis of caddyserver/caddy@50e54ee279 (2026-08-15).
Data as JSON: /api/errors/5954860cb4e5b00a.
Report an issue: GitHub.