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

  1. Print/log the url and method passed to Request and fix the malformed value (usually missing scheme like https:// or stray characters)
  2. url.Parse the URL before calling Request to validate it and surface the exact parse error
  3. Ensure base URL config (env var/config file) is a complete, correct absolute URL
  4. 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

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)