AlexxIT/go2rtc · error

nest: max retries exceeded

Error message

nest: max retries exceeded

What it means

ExchangeSDP retries the SDP exchange a limited number of times (e.g. to wait until the camera becomes available); if every attempt fails without producing an answer SDP, it gives up and returns this sentinel error. It is an exhaustion signal rather than a specific HTTP failure — each attempt had its own failure reason.

Solutions

  1. Fix the underlying per-attempt failure (check for an earlier 'nest: wrong status' error or logs) — refresh tokens, free the camera, restore connectivity.
  2. Stop competing stream clients so the camera becomes available within the retry window.
  3. Increase the retry count/delay if the camera is slow to become ready.
  4. Verify camera power/network status; a camera that never answers will always exhaust retries.

Example fix

// before
// 3 quick retries, camera still busy
answer, err := api.ExchangeSDP(ctx, offer)

// after
// stop other viewers first, then retry with longer window
stopOtherViewers(cameraID)
answer, err := api.ExchangeSDP(ctx, offer)
Defensive patterns

Strategy: fallback

Validate before calling

// check camera reachability before attempting SDP exchange
if !cameraOnline(cameraID) {
    return errors.New("camera offline; skipping SDP exchange")
}

Try / catch

answer, err := api.ExchangeSDP(ctx, offer)
if err != nil && strings.Contains(err.Error(), "max retries exceeded") {
    // stop competing viewers, wait, then fall back to snapshot stream
    stopOtherViewers(cameraID)
    return fallbackToSnapshotStream(ctx, cameraID)
}

Prevention

When it happens

Trigger: Calling ExchangeSDP when all retry attempts fail (camera busy/offline, token invalid, or transient Nest cloud errors persist across the whole retry window).

Common situations: Camera perpetually busy because another client holds the stream; camera offline/unreachable; credentials never refreshed so every attempt 401s; retry budget too small for slow cameras.

Understand the failure class

Background: Request timed out: what client-side request timeouts mean across libraries (Request timed out, TIMED_OUT, APITimeoutError) — this error's family across 39 libraries.

Related errors


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

Appendix: source

Thrown at pkg/nest/api.go:227

				Answer         string    `json:"answerSdp"`
				ExpiresAt      time.Time `json:"expiresAt"`
				MediaSessionID string    `json:"mediaSessionId"`
			} `json:"results"`
		}

		if err = json.NewDecoder(res.Body).Decode(&resv); err != nil {
			return "", err
		}

		a.StreamProjectID = projectID
		a.StreamDeviceID = deviceID
		a.StreamSessionID = resv.Results.MediaSessionID
		a.StreamExpiresAt = resv.Results.ExpiresAt

		return resv.Results.Answer, nil
	}

	return "", errors.New("nest: max retries exceeded")
}

func (a *API) refreshToken() error {
	// Get the cached API with matching token to get credentials
	var refreshKey string
	cacheMu.Lock()
	for key, api := range cache {
		if api.Token == a.Token {
			refreshKey = key
			break
		}
	}
	cacheMu.Unlock()

	if refreshKey == "" {
		return errors.New("nest: unable to find cached credentials")
	}

View on GitHub (pinned to c245815e75)