AlexxIT/go2rtc · error

email and password are required

Error message

email and password are required

What it means

When auth is provided as EmailAuth, both Email and Password must be non-empty; the factory rejects any partial credentials. The credentials are also used to build the client cache key, so empties are never acceptable.

Solutions

  1. Supply both Email and Password in the EmailAuth struct.
  2. Verify the config/env values feeding these fields are loaded before construction.
  3. Prefer RefreshTokenAuth if you have a refresh token — it is the more stable auth path.
  4. Add a startup validation that trims and checks both fields are non-empty.

Example fix

// before
auth := ring.EmailAuth{Email: cfg.Email} // password missing
// after
if cfg.Email == "" || cfg.Password == "" {
    return errors.New("ring email auth needs both email and password")
}
auth := ring.EmailAuth{Email: cfg.Email, Password: cfg.Password}
Defensive patterns

Strategy: validation

Validate before calling

if a.Email == "" || a.Password == "" { return errors.New("ring EmailAuth requires both email and password") }

Try / catch

client, err := ring.NewClient(auth)
if err != nil && strings.Contains(err.Error(), "email and password are required") {
    return fmt.Errorf("ring credentials incomplete in config: %w", err)
}

Prevention

When it happens

Trigger: Passing ring.EmailAuth{Email: "x@y.com"} without Password, or with both fields empty (zero-value struct).

Common situations: Config only sets username but not password (or password stored in a separate secret not loaded); password with only whitespace stripped to empty; migration from refresh-token auth left a half-populated EmailAuth.

Related errors


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

Appendix: source

Thrown at pkg/ring/api.go:168

	apiVersion         = 11
	defaultTimeout     = 20 * time.Second
	maxRetries         = 3
	sessionValidTime   = 12 * time.Hour
)

func NewRestClient(auth interface{}, onTokenRefresh func(string)) (*RingApi, error) {
	var cacheKey string

	// Create cache key based on auth data
	switch a := auth.(type) {
	case RefreshTokenAuth:
		if a.RefreshToken == "" {
			return nil, fmt.Errorf("refresh token is required")
		}
		cacheKey = "refresh:" + a.RefreshToken
	case EmailAuth:
		if a.Email == "" || a.Password == "" {
			return nil, fmt.Errorf("email and password are required")
		}
		cacheKey = "email:" + a.Email + ":" + a.Password
	default:
		return nil, fmt.Errorf("invalid auth type")
	}

	cacheMutex.Lock()
	defer cacheMutex.Unlock()

	if cachedClient, ok := clientCache[cacheKey]; ok {
		// Check if token is not nil and not expired
		if cachedClient.authToken != nil && time.Now().Before(cachedClient.tokenExpiry) {
			cachedClient.onTokenRefresh = onTokenRefresh
			return cachedClient, nil
		}
	}

	client := &RingApi{

View on GitHub (pinned to c245815e75)