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

  1. Create the API through NewAPI (which populates the credentials cache) before operations that may trigger refreshToken.
  2. Re-run the initial authentication flow after a process restart so the cache is repopulated.
  3. Ensure the username/password used matches the one the API was originally created with, so the cache key matches.
  4. 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

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


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.ExpiresAt

View on GitHub (pinned to c245815e75)