{"record":{"id":"7869e4383d1c947e","repo":"hashicorp/nomad","slug":"invalid-redirect-location-q-w","errorCode":null,"errorMessage":"invalid redirect location %q: %w","messagePattern":"invalid redirect location %q: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"api/api.go","lineNumber":1007,"sourceCode":"\t\twsScheme = \"wss\"\n\tdefault:\n\t\treturn nil, nil, fmt.Errorf(\"unsupported scheme: %v\", rhttp.URL.Scheme)\n\t}\n\trhttp.URL.Scheme = wsScheme\n\n\tconn, resp, err := dialer.Dial(rhttp.URL.String(), rhttp.Header)\n\n\t// check resp status code, as it's more informative than handshake error we get from ws library\n\tif resp != nil {\n\t\tswitch resp.StatusCode {\n\t\tcase http.StatusSwitchingProtocols:\n\t\t\t// Connection upgrade was successful.\n\n\t\tcase http.StatusPermanentRedirect, http.StatusTemporaryRedirect, http.StatusMovedPermanently:\n\t\t\tloc := resp.Header.Get(\"Location\")\n\t\t\tu, err := url.Parse(loc)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, nil, fmt.Errorf(\"invalid redirect location %q: %w\", loc, err)\n\t\t\t}\n\t\t\treturn c.websocket(u.Path, q)\n\n\t\tdefault:\n\t\t\tvar buf bytes.Buffer\n\n\t\t\tif resp.Header.Get(\"Content-Encoding\") == \"gzip\" {\n\t\t\t\tgreader, err := gzip.NewReader(resp.Body)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, nil, newUnexpectedResponseError(\n\t\t\t\t\t\tfromStatusCode(resp.StatusCode),\n\t\t\t\t\t\twithExpectedStatuses([]int{http.StatusSwitchingProtocols}),\n\t\t\t\t\t\twithError(err))\n\t\t\t\t}\n\t\t\t\t_, _ = io.Copy(&buf, greader)\n\t\t\t} else {\n\t\t\t\t_, _ = io.Copy(&buf, resp.Body)\n\t\t\t}","sourceCodeStart":989,"sourceCodeEnd":1025,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/api/api.go#L989-L1025","documentation":"In api/api.go:1007, when a websocket dial receives a redirect status (301/307/308), the client parses the Location header and retries the websocket at the new path. If Location cannot be parsed as a URL, it returns this error wrapping the url.Parse failure. Typically means the server or an intermediary emitted a malformed or empty Location header.","triggerScenarios":"Dialing a websocket (exec/logs) that gets answered with 301/307/308 whose Location header is missing or not a valid URL — commonly a badly configured proxy redirect or a redirect to a non-absolute/pct-encoded-broken target.","commonSituations":"Load balancers issuing redirects without Location; app-level handlers writing Location with invalid characters (raw spaces, control chars); redirect chains through proxies that mangle the header.","solutions":["curl -v the endpoint and inspect the raw Location header on the 3xx response","Fix the redirecting proxy/server to emit a valid absolute or path-absolute Location","Bypass the misbehaving intermediary and point the client directly at the Nomad agent/node address","If the redirect targets another region/node, ensure its address is correct and properly URL-encoded"],"exampleFix":"// before: LB returns \"Location: <nul>\"\nconn, _, err := c.websocket(path, q)\n// after: validate and redirect explicitly yourself\nresp, _ := http.Get(baseURL + path)\nloc := resp.Header.Get(\"Location\")\nif _, perr := url.Parse(loc); perr != nil { return fmt.Errorf(\"upstream %s returned bad Location %q\", baseURL, loc) }\nconn, _, err := c.websocket(path, q)","handlingStrategy":"validation","validationCode":"resp, err := http.Head(strings.TrimSuffix(baseURL, \"/\") + path)\nif err == nil && resp.StatusCode >= 300 && resp.StatusCode < 400 {\n\tif _, err := url.Parse(resp.Header.Get(\"Location\")); err != nil {\n\t\treturn fmt.Errorf(\"upstream emits invalid redirect Location %q\", resp.Header.Get(\"Location\"))\n\t}\n}","typeGuard":null,"tryCatchPattern":"conn, _, err := c.websocket(path, q)\nif err != nil && strings.Contains(err.Error(), \"invalid redirect location\") {\n\treturn fmt.Errorf(\"redirecting intermediary is misconfigured; connect directly to the node: %w\", err)\n}","preventionTips":["Avoid proxies that redirect websocket upgrade requests","Point the client directly at node HTTPAddr when following redirects fails","Test redirect chains with curl -v before deploying","Ensure Location headers are valid absolute or path-absolute URLs"],"tags":["websocket","redirect","http","nomad-api"],"backgroundTag":"invalid-redirect-location","analyzedSha":"482b49bf1aec006f089bcfc7e632d8f6ac303e5e","analyzedAt":"2026-09-04T07:54:14.808Z","contentChangedAt":"2026-09-04T07:54:14.808Z","schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}