Describe the bug
The nest: source crash-loops with a nil-pointer dereference panic in StartExtendStreamTimer. It became reproducible after Google migrated Nest accounts to the Google Home app: StreamExpiresAt now reports a very short remaining lifetime, so the extend-stream timer churns rapidly and reliably loses a race between the timer goroutine and StopExtendStreamTimer.
Version
1.9.14 — also present on current master (pkg/nest/api.go is unchanged).
Panic
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation]
goroutine N [running]:
github.com/AlexxIT/go2rtc/pkg/nest.(*API).StartExtendStreamTimer.func1()
.../pkg/nest/api.go:474
Root cause
func (a *API) StartExtendStreamTimer() {
if a.extendTimer != nil {
return
}
a.extendTimer = time.NewTimer(time.Until(a.StreamExpiresAt) - time.Minute)
go func() {
<-a.extendTimer.C // (api.go:474) reads a.extendTimer when the goroutine runs
...
}()
}
func (a *API) StopExtendStreamTimer() {
if a.extendTimer != nil {
a.extendTimer.Stop()
a.extendTimer = nil // niled concurrently with the goroutine above
}
}
The goroutine evaluates a.extendTimer.C when it runs. If StopExtendStreamTimer has already set a.extendTimer = nil (stream teardown / re-arm), the expression dereferences a nil *time.Timer and panics. With the shortened post-migration expiry, start/stop cycles happen constantly, so the race fires almost every time and the source never stays up.
Steps to reproduce
- Add a Nest source over WebRTC:
nest:?client_id=...&client_secret=...&refresh_token=...&project_id=...&device_id=...&protocols=WEB_RTC
- Consume it (e.g. via RTSP/WebRTC). The producer starts, then panics within a few extend cycles and crash-loops.
Suggested fix
Capture the timer channel locally so the goroutine never dereferences a.extendTimer:
a.extendTimer = time.NewTimer(time.Until(a.StreamExpiresAt) - time.Minute)
ch := a.extendTimer.C
go func() {
<-ch
...
}()
A done-channel variant additionally avoids a goroutine leak when the timer is stopped before it fires (the goroutine would otherwise block on the channel forever). Happy to open a PR.
Related issues
Describe the bug
The
nest:source crash-loops with a nil-pointer dereference panic inStartExtendStreamTimer. It became reproducible after Google migrated Nest accounts to the Google Home app:StreamExpiresAtnow reports a very short remaining lifetime, so the extend-stream timer churns rapidly and reliably loses a race between the timer goroutine andStopExtendStreamTimer.Version
1.9.14 — also present on current
master(pkg/nest/api.gois unchanged).Panic
Root cause
The goroutine evaluates
a.extendTimer.Cwhen it runs. IfStopExtendStreamTimerhas already seta.extendTimer = nil(stream teardown / re-arm), the expression dereferences a nil*time.Timerand panics. With the shortened post-migration expiry, start/stop cycles happen constantly, so the race fires almost every time and the source never stays up.Steps to reproduce
nest:?client_id=...&client_secret=...&refresh_token=...&project_id=...&device_id=...&protocols=WEB_RTCSuggested fix
Capture the timer channel locally so the goroutine never dereferences
a.extendTimer:A done-channel variant additionally avoids a goroutine leak when the timer is stopped before it fires (the goroutine would otherwise block on the channel forever). Happy to open a PR.
Related issues
StartExtendStreamTimer, the timer that drives that pre-expiry refresh — related symptom in the same subsystem (reconnect vs. crash). See also Add support for RTSP cameras for Nest source #1253.GenerateWebRtcStreamreturns 400 in 2026 (tightened offerSdp validation). Samenest:module and same mid-2026 Google breakage wave, but a distinct failure mode (WebRTC offer rejected at the API vs. an internal nil-pointer) — almost certainly a separate root cause.