AlexxIT/go2rtc · error
failed to create request
Error message
failed to create request: %w
What it means
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.
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
Example fix
// before
resp, err := api.Request("GET", baseURL + "/devices/" + deviceID, nil) // deviceID may contain spaces
// after
endpoint := baseURL + "/devices/" + url.PathEscape(deviceID)
if _, err := url.Parse(endpoint); err != nil {
return nil, fmt.Errorf("invalid endpoint %q: %w", endpoint, err)
}
resp, err := api.Request("GET", endpoint, nil) Defensive patterns
Strategy: validation
Validate before calling
// Go: validate URL and method before calling
func validRequest(method, rawURL string) error {
if _, err := url.Parse(rawURL); err != nil {
return fmt.Errorf("invalid url %q: %w", rawURL, err)
}
if !regexp.MustCompile(`^[A-Z]+$`).MatchString(method) {
return fmt.Errorf("invalid http method %q", method)
}
return nil
} Try / catch
// Go
if err := validRequest(method, url); err != nil {
return err // fail fast before invoking the API
}
resp, err := api.Request(method, url, body)
if err != nil && strings.Contains(err.Error(), "failed to create request") {
return fmt.Errorf("check method/url arguments: %w", err)
} Prevention
- 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
When it happens
Trigger: 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).
Common situations: 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.
Understand the failure class
Background: "Invalid URL" / "URL cannot be empty": fix the malformed or missing URL behind request-construction failures — this error's family across 50 libraries.
Related errors
AI-assisted analysis of AlexxIT/go2rtc@c245815e75 (2026-09-07).
Data as JSON: /api/errors/3c9f8ec720e4711d.
Report an issue: GitHub.
Appendix: source
Thrown at pkg/ring/api.go:421
func (c *RingApi) Request(method, url string, body interface{}) ([]byte, error) {
// Ensure we have a valid session
if err := c.ensureSession(); err != nil {
return nil, fmt.Errorf("session validation failed: %w", err)
}
var bodyReader io.Reader
if body != nil {
jsonBody, err := json.Marshal(body)
if err != nil {
return nil, fmt.Errorf("failed to marshal request body: %w", err)
}
bodyReader = bytes.NewReader(jsonBody)
}
// Create request
req, err := http.NewRequest(method, url, bodyReader)
if err != nil {
return nil, fmt.Errorf("failed to create request: %w", err)
}
// Set headers
req.Header.Set("Authorization", "Bearer "+c.authToken.AccessToken)
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Accept", "application/json")
req.Header.Set("hardware_id", c.hardwareID)
req.Header.Set("User-Agent", "android:com.ringapp")
// Make request with retries
var resp *http.Response
var responseBody []byte
for attempt := 0; attempt <= maxRetries; attempt++ {
resp, err = c.httpClient.Do(req)
if err != nil {
if attempt == maxRetries {
return nil, fmt.Errorf("request failed after %d retries: %w", maxRetries, err)View on GitHub (pinned to c245815e75)