AlexxIT/go2rtc · error
nest: unable to find cached credentials
Error message
nest: unable to find cached credentials
What it means
refreshToken locates the cached API credentials (keyed by a 'host:user:pass'-style composite key) whose token needs refreshing. If the cache walk finds no matching entry, refreshKey stays empty and this error is returned. It means the process has never successfully created an API for these credentials, so there is nothing to refresh from.
Solutions
- Create the API through NewAPI (which populates the credentials cache) before operations that may trigger refreshToken.
- Re-run the initial authentication flow after a process restart so the cache is repopulated.
- Ensure the username/password used matches the one the API was originally created with, so the cache key matches.
- If credentials must outlive the process, persist them externally and re-register via NewAPI at startup.
Example fix
// before
api := &nest.API{...} // built manually; not in cache
answer, err := api.ExchangeSDP(ctx, offer)
// after
api, err := nest.NewAPI(ctx, refreshToken) // registers cache entry
answer, err := api.ExchangeSDP(ctx, offer) Defensive patterns
Strategy: validation
Validate before calling
// ensure the API was created via NewAPI so credentials are cached
if !apiWasCreatedViaNewAPI {
api, err = nest.NewAPI(ctx, refreshToken)
if err != nil { return err }
} Try / catch
answer, err := api.ExchangeSDP(ctx, offer)
if err != nil && strings.Contains(err.Error(), "unable to find cached credentials") {
// rebuild the API through NewAPI to repopulate the credential cache
api, cerr = nest.NewAPI(ctx, storedRefreshToken)
if cerr != nil { return cerr }
answer, err = api.ExchangeSDP(ctx, offer)
} Prevention
- Always construct nest APIs via NewAPI; never instantiate the struct directly.
- Re-authenticate after process restarts to rebuild the in-memory cache.
- Keep credential fields stable so cache keys match across calls.
- Persist refresh tokens externally if sessions must survive restarts.
When it happens
Trigger: Calling refreshToken (via ExchangeSDP) when the credentials cache contains no entry matching the API's credentials — e.g. NewAPI was never called successfully in this process, or the cache was cleared.
Common situations: Constructing an API manually/by hand instead of via NewAPI so it never registered in the cache; process restart wiping the in-memory cache; credentials changed so the cache key no longer matches.
Related errors
- credentials: storage not initialized
- hap: can't dial witout client_id or client_private
- nest: wrong status
- nest: max retries exceeded
- nest: invalid cache key format
AI-assisted analysis of AlexxIT/go2rtc@c245815e75 (2026-09-07).
Data as JSON: /api/errors/d88b204072fb5d43.
Report an issue: GitHub.
Appendix: source
Thrown at pkg/nest/api.go:243
}
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")
}
// Parse credentials from cache key
parts := strings.Split(refreshKey, ":")
if len(parts) != 3 {
return errors.New("nest: invalid cache key format")
}
clientID, clientSecret, refreshToken := parts[0], parts[1], parts[2]
// Get new API instance which will refresh the token
newAPI, err := NewAPI(clientID, clientSecret, refreshToken)
if err != nil {
return err
}
// Update current API with new token
a.Token = newAPI.Token
a.ExpiresAt = newAPI.ExpiresAtView on GitHub (pinned to c245815e75)