AlexxIT/go2rtc · error

onvif: wrong response

Error message

onvif: wrong response ${res.Status}

What it means

Request in pkg/onvif/client.go performs the HTTP POST of the SOAP envelope to the resolved ONVIF service URL and, if the HTTP response status is anything other than 200 OK, returns errors.New("onvif: wrong response "+res.Status). The res.Status text includes the numeric code and reason phrase, so this is the ONVIF device rejecting the request at the HTTP transport layer before any SOAP body parsing happens.

Solutions

  1. Check the numeric code in the message: 401 means fix credentials — pass correct username:password in the device URL userinfo and re-dial
  2. Confirm the service URL scheme/port matches the camera (http vs https, port 80/8899/etc.) via GetCapabilities/GetServices
  3. Retry after a delay for 5xx — cameras commonly return 503 while rebooting or under load
  4. Capture the response body with a raw HTTP client/proxy to see whether the camera returned a SOAP fault with the status
  5. Update camera firmware if it returns 400/500 for spec-compliant requests

Example fix

// before
uri, err := cam.GetStreamUri(...) // "onvif: wrong response 401 Unauthorized"
// after
// ensure credentials are part of the dial URL
u, _ := url.Parse("onvif://admin:correctpass@192.168.1.64:80/onvif/device_service")
cam, err := onvif.Dial(ctx, u)
if err != nil { return err }
uri, err := cam.GetStreamUri(...)
Defensive patterns

Strategy: retry

Validate before calling

if u.User == nil || u.User.Username() == "" {
    return errors.New("onvif: device URL missing credentials")
}

Type guard

func isHTTPStatusErr(err error, code string) bool {
    return err != nil && strings.Contains(err.Error(), "onvif: wrong response "+code)
}

Try / catch

var data []byte
for i := 0; i < 3; i++ {
    data, err = cam.DeviceRequest(ctx, op)
    if err == nil { break }
    if strings.Contains(err.Error(), "401") {
        return fmt.Errorf("onvif auth failed: check credentials in device URL")
    }
    if strings.Contains(err.Error(), "onvif: wrong response 5") {
        time.Sleep(time.Duration(1<<i) * time.Second)
        continue
    }
    return err
}

Prevention

When it happens

Trigger: Any ONVIF call (GetProfile, GetStreamUri, GetSnapshotUri, GetServiceCapabilities, DeviceRequest, etc.) against a camera that answers 401 Unauthorized (bad/missing credentials in the URL userinfo), 404 (wrong service path), 405, or 5xx (device overloaded/rebooting).

Common situations: Wrong username/password (or wrong digest-auth handling) in the ONVIF URL; camera firmware changing service paths; camera mid-reboot returning 503; calling an HTTPS URL on an HTTP-only port or vice versa; WS-Addressing/Action headers rejected by stricter firmwares returning 400/500.

Related errors


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

Appendix: source

Thrown at pkg/onvif/client.go:193

}

func (c *Client) Request(url, body string) ([]byte, error) {
	if url == "" {
		return nil, errors.New("onvif: unsupported service")
	}

	e := NewEnvelopeWithUser(c.url.User)
	e.Append(body)

	client := &http.Client{Timeout: time.Second * 5000}
	res, err := client.Post(url, `application/soap+xml;charset=utf-8`, bytes.NewReader(e.Bytes()))
	if err != nil {
		return nil, err
	}
	defer res.Body.Close()

	if res.StatusCode != http.StatusOK {
		return nil, errors.New("onvif: wrong response " + res.Status)
	}

	return io.ReadAll(res.Body)
}

View on GitHub (pinned to c245815e75)