AlexxIT/go2rtc · error

res.Status

Error message

res.Status

What it means

The HTTP source producer's do() requires the upstream server to answer with HTTP 200 OK. Any other status code causes the library to return an error built from res.Status (e.g. "404 Not Found"), aborting the stream. The error message is literally the upstream HTTP status line, surfacing the remote server's response to the caller.

Solutions

  1. Open the source URL in a browser/curl and confirm it returns 200 with the expected stream
  2. Fix credentials in the URL or config (http://user:pass@host/... or Authorization header)
  3. Correct the URL path/port in the stream source configuration
  4. Check upstream server health; handle redirects by using the final URL directly

Example fix

// before
streams: {cam: "http://cam.local/wrong/path"}
// after
streams: {cam: "http://user:pass@cam.local/mjpeg/1"}
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-check the source URL returns 200 before configuring it
curl -f -u user:pass http://cam.local/mjpeg/1 -o /dev/null

Try / catch

// Go
prod, err := do(req)
if err != nil {
    var status string
    if strings.Contains(err.Error(), " ") { // e.g. "404 Not Found"
        status = err.Error()
    }
    log.Printf("http source failed (%s): %v", status, err)
    return err
}

Prevention

When it happens

Trigger: Dialing an HTTP source URL that returns a non-200 response: 401/403 wrong credentials, 404 wrong path, 500 server error, or a redirect that isn't followed to a 200.

Common situations: MJPEG/HTTP camera URLs with expired basic-auth credentials, wrong port or path in the stream config, camera web UI returning 302 to a login page, or upstream server temporarily failing.

Related errors


AI-assisted analysis of AlexxIT/go2rtc@c245815e75 (2026-09-07). Data as JSON: /api/errors/4bebec906ac851f5. Report an issue: GitHub.

Appendix: source

Thrown at internal/http/http.go:70

	}

	if info, ok := prod.(core.Info); ok {
		info.SetProtocol("http")
		info.SetRemoteAddr(req.URL.Host) // TODO: rewrite to net.Conn
		info.SetURL(rawURL)
	}

	return prod, nil
}

func do(req *http.Request) (core.Producer, error) {
	res, err := tcp.Do(req)
	if err != nil {
		return nil, err
	}

	if res.StatusCode != http.StatusOK {
		return nil, errors.New(res.Status)
	}

	// 1. Guess format from content type
	ct := res.Header.Get("Content-Type")
	if i := strings.IndexByte(ct, ';'); i > 0 {
		ct = ct[:i]
	}

	var ext string
	if i := strings.LastIndexByte(req.URL.Path, '.'); i > 0 {
		ext = req.URL.Path[i+1:]
	}

	switch {
	case ct == "application/vnd.apple.mpegurl" || ext == "m3u8":
		return hls.OpenURL(req.URL, res.Body)
	case ct == "image/jpeg":
		return image.Open(res)

View on GitHub (pinned to c245815e75)