{"record":{"id":"3c9f8ec720e4711d","repo":"AlexxIT/go2rtc","slug":"failed-to-create-request-w","errorCode":null,"errorMessage":"failed to create request: %w","messagePattern":"failed to create request: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/ring/api.go","lineNumber":421,"sourceCode":"func (c *RingApi) Request(method, url string, body interface{}) ([]byte, error) {\n\t// Ensure we have a valid session\n\tif err := c.ensureSession(); err != nil {\n\t\treturn nil, fmt.Errorf(\"session validation failed: %w\", err)\n\t}\n\n\tvar bodyReader io.Reader\n\tif body != nil {\n\t\tjsonBody, err := json.Marshal(body)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to marshal request body: %w\", err)\n\t\t}\n\t\tbodyReader = bytes.NewReader(jsonBody)\n\t}\n\n\t// Create request\n\treq, err := http.NewRequest(method, url, bodyReader)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to create request: %w\", err)\n\t}\n\n\t// Set headers\n\treq.Header.Set(\"Authorization\", \"Bearer \"+c.authToken.AccessToken)\n\treq.Header.Set(\"Content-Type\", \"application/json\")\n\treq.Header.Set(\"Accept\", \"application/json\")\n\treq.Header.Set(\"hardware_id\", c.hardwareID)\n\treq.Header.Set(\"User-Agent\", \"android:com.ringapp\")\n\n\t// Make request with retries\n\tvar resp *http.Response\n\tvar responseBody []byte\n\n\tfor attempt := 0; attempt <= maxRetries; attempt++ {\n\t\tresp, err = c.httpClient.Do(req)\n\t\tif err != nil {\n\t\t\tif attempt == maxRetries {\n\t\t\t\treturn nil, fmt.Errorf(\"request failed after %d retries: %w\", maxRetries, err)","sourceCodeStart":403,"sourceCodeEnd":439,"githubUrl":"https://github.com/AlexxIT/go2rtc/blob/c245815e75e2a5fd60b4290f12bfc04e55a984d3/pkg/ring/api.go#L403-L439","documentation":"RingApi.Request builds an *http.Request via http.NewRequest(method, url, bodyReader). If that call errors — almost always because the URL string is malformed or the HTTP method string is invalid — this error is returned and no request is sent.","triggerScenarios":"Calling Request with an unparseable URL (missing scheme, spaces, control characters) or an invalid method token containing characters outside the token grammar (e.g. spaces or non-ASCII).","commonSituations":"Concatenating base URL + path incorrectly (missing slash, double slash), reading a base URL from a misconfigured env var, template placeholders like {{id}} left unsubstituted, or embedding a space in the method name.","solutions":["Print/log the url and method passed to Request and fix the malformed value (usually missing scheme like https:// or stray characters)","url.Parse the URL before calling Request to validate it and surface the exact parse error","Ensure base URL config (env var/config file) is a complete, correct absolute URL","URL-escape path/query components with url.PathEscape/url.QueryEscape instead of raw string concatenation"],"exampleFix":"// before\nresp, err := api.Request(\"GET\", baseURL + \"/devices/\" + deviceID, nil) // deviceID may contain spaces\n// after\nendpoint := baseURL + \"/devices/\" + url.PathEscape(deviceID)\nif _, err := url.Parse(endpoint); err != nil {\n    return nil, fmt.Errorf(\"invalid endpoint %q: %w\", endpoint, err)\n}\nresp, err := api.Request(\"GET\", endpoint, nil)","handlingStrategy":"validation","validationCode":"// Go: validate URL and method before calling\nfunc validRequest(method, rawURL string) error {\n    if _, err := url.Parse(rawURL); err != nil {\n        return fmt.Errorf(\"invalid url %q: %w\", rawURL, err)\n    }\n    if !regexp.MustCompile(`^[A-Z]+$`).MatchString(method) {\n        return fmt.Errorf(\"invalid http method %q\", method)\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":"// Go\nif err := validRequest(method, url); err != nil {\n    return err // fail fast before invoking the API\n}\nresp, err := api.Request(method, url, body)\nif err != nil && strings.Contains(err.Error(), \"failed to create request\") {\n    return fmt.Errorf(\"check method/url arguments: %w\", err)\n}","preventionTips":["Store the Ring base URL in one config constant and build paths with url.JoinPath or path.Join","Always escape dynamic path/query segments (url.PathEscape/QueryEscape)","Add a startup-time config check that url.Parse succeeds on the configured base URL","Avoid string concatenation with template placeholders; substitute before calling"],"tags":["http","url","request"],"backgroundTag":"invalid-url","analyzedSha":"c245815e75e2a5fd60b4290f12bfc04e55a984d3","analyzedAt":"2026-09-07T11:47:02.965Z","contentChangedAt":"2026-09-07T11:47:02.965Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}