AlexxIT/go2rtc · warning

unsupported operation

Error message

unsupported operation

What it means

go2rtc's built-in ONVIF server only implements a fixed whitelist of ONVIF Device/Media operations (the switch in onvifDeviceService). When the parsed SOAP action does not match any supported case, the default branch returns 400 "unsupported operation" and logs the operation name plus the raw request at warn/debug level. This is an intentional limitation of the emulated ONVIF device.

Solutions

  1. Check the warn log line 'unsupported operation: X' to see exactly which call was rejected
  2. Upgrade go2rtc — new releases regularly add supported ONVIF operations
  3. Configure the client to use only RTSP streaming / basic discovery features rather than full ONVIF control
  4. Implement or contribute the missing operation in internal/onvif/onvif.go's switch
  5. File/consult a go2rtc GitHub issue for the specific operation

Example fix

null
Defensive patterns

Strategy: fallback

Validate before calling

supportedOps := map[string]bool{
    "GetCapabilities": true, "GetServices": true, "GetDeviceInformation": true,
    "GetVideoSources": true, "GetProfiles": true, "GetProfile": true,
    "GetStreamUri": true, "GetSnapshotUri": true, "SystemReboot": true,
}
if !supportedOps[op] { useRtspDirectly = true }

Try / catch

if resp.StatusCode == http.StatusBadRequest {
    b, _ := io.ReadAll(resp.Body)
    if strings.Contains(string(b), "unsupported operation") {
        // fall back to plain RTSP/HTTP streaming instead of ONVIF control
        return buildRtspSource(camera)
    }
}

Prevention

When it happens

Trigger: An ONVIF client (e.g. Home Assistant, an NVR) sends an operation go2rtc has not implemented, such as PTZ commands, GetVideoEncoderConfiguration for advanced setup, events, or firmware operations.

Common situations: Home Assistant or an NVR probing advanced ONVIF features; newer ONVIF Profile operations not in go2rtc's whitelist; third-party ONVIF tools testing full device compatibility against the emulator.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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

Appendix: source

Thrown at internal/onvif/onvif.go:147

	case onvif.MediaGetVideoSourceConfiguration:
		token := onvif.FindTagValue(b, "ConfigurationToken")
		b = onvif.GetVideoSourceConfigurationResponse(token)

	case onvif.MediaGetStreamUri:
		host, _, err := net.SplitHostPort(r.Host)
		if err != nil {
			host = r.Host // in case of Host without port
		}

		uri := "rtsp://" + host + ":" + rtsp.Port + "/" + onvif.FindTagValue(b, "ProfileToken")
		b = onvif.GetStreamUriResponse(uri)

	case onvif.MediaGetSnapshotUri:
		uri := "http://" + r.Host + "/api/frame.jpeg?src=" + onvif.FindTagValue(b, "ProfileToken")
		b = onvif.GetSnapshotUriResponse(uri)

	default:
		http.Error(w, "unsupported operation", http.StatusBadRequest)
		log.Warn().Msgf("[onvif] unsupported operation: %s", operation)
		log.Debug().Msgf("[onvif] unsupported request:\n%s", b)
		return
	}

	log.Trace().Msgf("[onvif] server response:\n%s", b)

	w.Header().Set("Content-Type", "application/soap+xml; charset=utf-8")
	if _, err = w.Write(b); err != nil {
		log.Error().Err(err).Caller().Send()
	}
}

func apiOnvif(w http.ResponseWriter, r *http.Request) {
	src := r.URL.Query().Get("src")

	var items []*api.Source

View on GitHub (pinned to c245815e75)