{"record":{"id":"610d1aafca266174","repo":"juanfont/headscale","slug":"s-creating-confirm-request-w","errorCode":null,"errorMessage":"%s creating confirm request: %w","messagePattern":"(.+?) creating confirm request: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"integration/scenario.go","lineNumber":1314,"sourceCode":"\t// Build the absolute POST URL from the response's request URL.\n\tbase := prevResp.Request.URL\n\tconfirmURL := &url.URL{\n\t\tScheme: base.Scheme,\n\t\tHost:   base.Host,\n\t\tPath:   formAction,\n\t}\n\n\tlog.Printf(\"%s auto-submitting confirm form: %s\", hostname, confirmURL)\n\n\tformData := url.Values{\n\t\t\"headscale_register_confirm\": {csrfToken},\n\t}\n\n\tctx := context.Background()\n\n\treq, err := http.NewRequestWithContext(ctx, http.MethodPost, confirmURL.String(), strings.NewReader(formData.Encode()))\n\tif err != nil {\n\t\treturn \"\", nil, fmt.Errorf(\"%s creating confirm request: %w\", hostname, err)\n\t}\n\n\treq.Header.Set(\"Content-Type\", \"application/x-www-form-urlencoded\")\n\n\tconfirmResp, err := hc.Do(req)\n\tif err != nil {\n\t\treturn \"\", nil, fmt.Errorf(\"%s sending confirm request: %w\", hostname, err)\n\t}\n\tdefer confirmResp.Body.Close()\n\n\tconfirmBytes, err := io.ReadAll(confirmResp.Body)\n\tif err != nil {\n\t\treturn \"\", nil, fmt.Errorf(\"%s reading confirm response: %w\", hostname, err)\n\t}\n\n\tif confirmResp.StatusCode != http.StatusOK {\n\t\treturn string(confirmBytes), nil, fmt.Errorf( //nolint:err113\n\t\t\t\"%s confirm returned status %d: %s\",","sourceCodeStart":1296,"sourceCodeEnd":1332,"githubUrl":"https://github.com/juanfont/headscale/blob/565fd254d06c4c7f9a8cad1714a43445c79ba420/integration/scenario.go#L1296-L1332","documentation":"`http.NewRequestWithContext` failed while building the POST that auto-submits the confirm form. This is Go's standard request constructor complaining about the assembled URL (scheme/host/path) or the body reader — the confirm URL built from `prevResp.Request.URL` plus the scraped form action was not parseable.","triggerScenarios":"`confirmURL.String()` is malformed — e.g. the scraped `formAction` contains characters that make the URL invalid for `http.NewRequestWithContext`, or scheme/host are empty because `prevResp.Request` was nil-adjacent/mis-set.","commonSituations":"The form action scrape picked up garbage (HTML-escaped characters like &amp;); a code path where `prevResp` is not the page that rendered the form; localhost URL built with an empty Host.","solutions":["Log `confirmURL.String()` right before building the request and eyeball scheme/host/path.","Sanitize the scraped action: `html.UnescapeString(formAction)` and `url.PathUnescape` as appropriate.","Fall back to `base.ResolveReference(parsedAction)` instead of manually copying Scheme/Host/Path so relative actions resolve correctly."],"exampleFix":"// before\nconfirmURL := &url.URL{Scheme: base.Scheme, Host: base.Host, Path: formAction}\n\n// after\nref, err := url.Parse(html.UnescapeString(formAction))\nif err != nil {\n    return \"\", nil, fmt.Errorf(\"%s confirm form: bad action URL %q: %w\", hostname, formAction, err)\n}\nconfirmURL := base.ResolveReference(ref)","handlingStrategy":"validation","validationCode":"// Validate the action before building the request.\nref, err := url.Parse(html.UnescapeString(formAction))\nif err != nil || ref.Path == \"\" {\n    return \"\", nil, fmt.Errorf(\"%s confirm form: unusable action %q\", hostname, formAction)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["HTML-unescape scraped URLs before parsing.","Use base.ResolveReference for relative form actions.","Unit-test the URL assembly with the known template output."],"tags":["http","integration","url-parsing"],"backgroundTag":null,"analyzedSha":"565fd254d06c4c7f9a8cad1714a43445c79ba420","analyzedAt":"2026-08-15T13:12:30.133Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}