{"record":{"id":"5a27c74948a91e03","repo":"AlexxIT/go2rtc","slug":"nest-failed-to-generate-rtsp-url","errorCode":null,"errorMessage":"nest: failed to generate rtsp url","messagePattern":"nest: failed to generate rtsp url","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/nest/api.go","lineNumber":375,"sourceCode":"\tif res.StatusCode != 200 {\n\t\treturn \"\", errors.New(\"nest: wrong status: \" + res.Status)\n\t}\n\n\tvar resv struct {\n\t\tResults struct {\n\t\t\tStreamURLs           map[string]string `json:\"streamUrls\"`\n\t\t\tStreamExtensionToken string            `json:\"streamExtensionToken\"`\n\t\t\tStreamToken          string            `json:\"streamToken\"`\n\t\t\tExpiresAt            time.Time         `json:\"expiresAt\"`\n\t\t} `json:\"results\"`\n\t}\n\n\tif err = json.NewDecoder(res.Body).Decode(&resv); err != nil {\n\t\treturn \"\", err\n\t}\n\n\tif _, ok := resv.Results.StreamURLs[\"rtspUrl\"]; !ok {\n\t\treturn \"\", errors.New(\"nest: failed to generate rtsp url\")\n\t}\n\n\ta.StreamProjectID = projectID\n\ta.StreamDeviceID = deviceID\n\ta.StreamToken = resv.Results.StreamToken\n\ta.StreamExtensionToken = resv.Results.StreamExtensionToken\n\ta.StreamExpiresAt = resv.Results.ExpiresAt\n\n\treturn resv.Results.StreamURLs[\"rtspUrl\"], nil\n}\n\nfunc (a *API) StopRTSPStream() error {\n\tif a.StreamProjectID == \"\" || a.StreamDeviceID == \"\" {\n\t\treturn errors.New(\"nest: tried to stop rtsp stream without a project or device ID\")\n\t}\n\n\tvar reqv struct {\n\t\tCommand string `json:\"command\"`","sourceCodeStart":357,"sourceCodeEnd":393,"githubUrl":"https://github.com/AlexxIT/go2rtc/blob/c245815e75e2a5fd60b4290f12bfc04e55a984d3/pkg/nest/api.go#L357-L393","documentation":"GenerateRtspStream (pkg/nest/api.go:375) got a 200 response but the decoded results contain no \"rtspUrl\" key in the streamUrls map. The library treats a missing RTSP URL as a failed stream generation even though the HTTP call succeeded.","triggerScenarios":"Nest returns 200 with a streamUrls map that lacks the \"rtspUrl\" entry — e.g. the camera does not support RTSP, the SDM response shape changed, or the command silently failed with an empty results payload.","commonSituations":"Doorbell or battery cameras that don't expose RTSP; Nest API contract/field changes; devices streaming via WebRTC only; partially successful command responses with empty streamUrls.","solutions":["Confirm the specific camera model supports RTSP streaming via the SDM API (many battery/doorbell devices do not).","Log the full resv.Results payload to see what keys were actually returned and adapt parsing.","Fall back to WebRTC streaming (ExchangeSDP path) if RTSP is unsupported for the device.","Check for Nest API changelog updates that may have renamed or moved the streamUrls.rtspUrl field."],"exampleFix":"// before: assuming rtspUrl always exists\nurl, err := api.GenerateRtspStream(projectID, deviceID)\n// after: validate device support and handle absence\ndevice, _ := sdm.GetDevice(deviceID)\nif !device.SupportsRtsp() { return useWebRtc(device) }\nurl, err := api.GenerateRtspStream(projectID, deviceID)","handlingStrategy":"fallback","validationCode":"device, err := sdmClient.GetDevice(ctx, deviceID)\nif err != nil { return err }\nif !device.Traits[\"sdm.devices.traits.CameraLiveStream\"].SupportsRtsp { return useWebRtcFallback(deviceID) }","typeGuard":"func hasRtspUrl(results struct{ StreamURLs map[string]string }) bool {\n    u, ok := results.StreamURLs[\"rtspUrl\"]\n    return ok && u != \"\"\n}","tryCatchPattern":"url, err := api.GenerateRtspStream(projectID, deviceID)\nif err != nil && strings.Contains(err.Error(), \"failed to generate rtsp url\") {\n    return startWebRtcStream(deviceID) // device likely lacks RTSP\n}\nif err != nil { return err }","preventionTips":["Check the device's CameraLiveStream trait/supportedProtocols before choosing RTSP.","Log the full generate response body when this error occurs to capture the actual shape.","Implement a WebRTC (ExchangeSDP) fallback path for non-RTSP cameras.","Watch the Nest SDM API changelog for streamUrls field changes."],"tags":["api","rtsp","response-parsing","streaming"],"backgroundTag":"unexpected-response-shape","analyzedSha":"c245815e75e2a5fd60b4290f12bfc04e55a984d3","analyzedAt":"2026-09-07T11:47:02.965Z","contentChangedAt":"2026-09-07T11:47:02.965Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}