{"record":{"id":"5954860cb4e5b00a","repo":"caddyserver/caddy","slug":"unsupported-http-version-s-supported-version","errorCode":null,"errorMessage":"unsupported HTTP version: %s, supported version: %s","messagePattern":"unsupported HTTP version: (.+?), supported version: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"modules/caddyhttp/reverseproxy/httptransport.go","lineNumber":193,"sourceCode":"}\n\nvar (\n\tallowedVersions       = []string{\"1.1\", \"2\", \"h2c\", \"3\"}\n\tallowedVersionsString = strings.Join(allowedVersions, \", \")\n)\n\n// Provision sets up h.Transport with a *http.Transport\n// that is ready to use.\nfunc (h *HTTPTransport) Provision(ctx caddy.Context) error {\n\tif len(h.Versions) == 0 {\n\t\th.Versions = []string{\"1.1\", \"2\"}\n\t}\n\t// some users may provide http versions not recognized by caddy, instead of trying to\n\t// guess the version, we just error out and let the user fix their config\n\t// see: https://github.com/caddyserver/caddy/issues/7111\n\tfor _, v := range h.Versions {\n\t\tif !slices.Contains(allowedVersions, v) {\n\t\t\treturn fmt.Errorf(\"unsupported HTTP version: %s, supported version: %s\", v, allowedVersionsString)\n\t\t}\n\t}\n\n\trt, err := h.NewTransport(ctx)\n\tif err != nil {\n\t\treturn err\n\t}\n\th.Transport = rt\n\n\treturn nil\n}\n\n// NewTransport builds a standard-lib-compatible http.Transport value from h.\nfunc (h *HTTPTransport) NewTransport(caddyCtx caddy.Context) (*http.Transport, error) {\n\t// Set keep-alive defaults if it wasn't otherwise configured\n\tif h.KeepAlive == nil {\n\t\th.KeepAlive = new(KeepAlive)\n\t}","sourceCodeStart":175,"sourceCodeEnd":211,"githubUrl":"https://github.com/caddyserver/caddy/blob/50e54ee279aa1e504fe218ca49ab6ae16c100410/modules/caddyhttp/reverseproxy/httptransport.go#L175-L211","documentation":"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.","triggerScenarios":"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.","commonSituations":"Assuming nginx-style version tokens (http2, 1.0), typos like `verions`, or copying config between Caddy versions without checking the directive's allowed values.","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"],"exampleFix":"# before\nreverse_proxy localhost:9000 {\n\ttransport http {\n\t\tversions 2.0 1\n\t}\n}\n# after\nreverse_proxy localhost:9000 {\n\ttransport http {\n\t\tversions 1.1 2\n\t}\n}","handlingStrategy":"validation","validationCode":"var allowedVersions = map[string]bool{\"1.1\": true, \"2\": true, \"3\": true}\nfor _, v := range h.Versions {\n\tif !allowedVersions[v] {\n\t\treturn fmt.Errorf(\"bad version %q; want 1.1, 2 or 3\", v)\n\t}\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Copy the literal allowed values from the error message into config templates","Note there is no \"1\" or \"2.0\" — exact strings only"],"tags":["reverse-proxy","http-transport","validation","config"],"backgroundTag":null,"analyzedSha":"50e54ee279aa1e504fe218ca49ab6ae16c100410","analyzedAt":"2026-08-15T09:20:21.641Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}