{"record":{"id":"02d22e85c2b743d3","repo":"wtfutil/wtf","slug":"creating-request-w","errorCode":null,"errorMessage":"creating request: %w","messagePattern":"creating request: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"modules/devto/client.go","lineNumber":64,"sourceCode":"\n\tq := u.Query()\n\tif tag != \"\" {\n\t\tq.Set(\"tag\", tag)\n\t}\n\tif username != \"\" {\n\t\tq.Set(\"username\", username)\n\t}\n\tif state != \"\" {\n\t\tq.Set(\"state\", state)\n\t}\n\tif perPage > 0 {\n\t\tq.Set(\"per_page\", fmt.Sprintf(\"%d\", perPage))\n\t}\n\tu.RawQuery = q.Encode()\n\n\treq, err := http.NewRequestWithContext(ctx, http.MethodGet, u.String(), nil)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"creating request: %w\", err)\n\t}\n\n\tresp, err := c.httpClient.Do(req)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"executing request: %w\", err)\n\t}\n\tdefer resp.Body.Close()\n\n\tif resp.StatusCode != http.StatusOK {\n\t\treturn nil, fmt.Errorf(\"unexpected status %d from DEV.to API\", resp.StatusCode)\n\t}\n\n\tvar articles []Article\n\tif err := json.NewDecoder(resp.Body).Decode(&articles); err != nil {\n\t\treturn nil, fmt.Errorf(\"decoding response: %w\", err)\n\t}\n\n\treturn articles, nil","sourceCodeStart":46,"sourceCodeEnd":82,"githubUrl":"https://github.com/wtfutil/wtf/blob/bb838c1ccb0f0f3223690df44afdec663d622881/modules/devto/client.go#L46-L82","documentation":"FetchArticles wraps errors from http.NewRequestWithContext as 'creating request'. This means the request object could not be built — almost always because the composed URL string is malformed (bad method, unparsable URL) — and occurs before any network I/O.","triggerScenarios":"http.NewRequestWithContext returns an error when building the GET request to u.String() — typically because query encoding or baseURL parsing produced an invalid URL (e.g. invalid characters in tag/username/state filter values).","commonSituations":"User-supplied filter values containing spaces or illegal URL characters interpolated into the URL; context already canceled before request creation; misconfigured baseURL leaking into the final URL.","solutions":["Sanitize/validate filter inputs (tag, username, state) before calling FetchArticles","Log u.String() just before building the request to inspect the final URL","Ensure the context passed in is not already canceled and the URL parses cleanly"],"exampleFix":"// before\narticles, err := client.FetchArticles(ctx, \"go lang\", \"\", \"\", 10) // space in tag → bad URL\n// after\narticles, err := client.FetchArticles(ctx, \"go-lang\", \"\", \"\", 10)\n// or url.QueryEscape(userTag) before interpolating","handlingStrategy":"validation","validationCode":"func sanitizeFilter(s string) string {\n    return url.QueryEscape(strings.TrimSpace(s))\n}\ntag, user, state := sanitizeFilter(tag), sanitizeFilter(user), sanitizeFilter(state)\narticles, err := client.FetchArticles(ctx, tag, user, state, perPage)","typeGuard":null,"tryCatchPattern":"articles, err := client.FetchArticles(ctx, tag, user, state, perPage)\nif err != nil {\n    if errors.Is(err, context.Canceled) || errors.Is(err, context.DeadlineExceeded) {\n        return nil, err // caller-owned context issue\n    }\n    return nil, fmt.Errorf(\"devto: %w\", err)\n}","preventionTips":["URL-escape all user-supplied filter values","Check that contexts passed in aren't already canceled","Inspect the fully assembled URL in a unit test"],"tags":["devto","http","url","go"],"backgroundTag":"http-request-construction-failed","analyzedSha":"bb838c1ccb0f0f3223690df44afdec663d622881","analyzedAt":"2026-09-03T17:02:45.030Z","contentChangedAt":"2026-09-03T17:02:45.030Z","schemaVersion":2},"datasetVersion":"2026-09-11T00:17:11.886Z"}