{"record":{"id":"4f63804876f9975a","repo":"AlexxIT/go2rtc","slug":"email-and-password-are-required","errorCode":null,"errorMessage":"email and password are required","messagePattern":"email and password are required","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/ring/api.go","lineNumber":168,"sourceCode":"\tapiVersion         = 11\n\tdefaultTimeout     = 20 * time.Second\n\tmaxRetries         = 3\n\tsessionValidTime   = 12 * time.Hour\n)\n\nfunc NewRestClient(auth interface{}, onTokenRefresh func(string)) (*RingApi, error) {\n\tvar cacheKey string\n\n\t// Create cache key based on auth data\n\tswitch a := auth.(type) {\n\tcase RefreshTokenAuth:\n\t\tif a.RefreshToken == \"\" {\n\t\t\treturn nil, fmt.Errorf(\"refresh token is required\")\n\t\t}\n\t\tcacheKey = \"refresh:\" + a.RefreshToken\n\tcase EmailAuth:\n\t\tif a.Email == \"\" || a.Password == \"\" {\n\t\t\treturn nil, fmt.Errorf(\"email and password are required\")\n\t\t}\n\t\tcacheKey = \"email:\" + a.Email + \":\" + a.Password\n\tdefault:\n\t\treturn nil, fmt.Errorf(\"invalid auth type\")\n\t}\n\n\tcacheMutex.Lock()\n\tdefer cacheMutex.Unlock()\n\n\tif cachedClient, ok := clientCache[cacheKey]; ok {\n\t\t// Check if token is not nil and not expired\n\t\tif cachedClient.authToken != nil && time.Now().Before(cachedClient.tokenExpiry) {\n\t\t\tcachedClient.onTokenRefresh = onTokenRefresh\n\t\t\treturn cachedClient, nil\n\t\t}\n\t}\n\n\tclient := &RingApi{","sourceCodeStart":150,"sourceCodeEnd":186,"githubUrl":"https://github.com/AlexxIT/go2rtc/blob/c245815e75e2a5fd60b4290f12bfc04e55a984d3/pkg/ring/api.go#L150-L186","documentation":"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.","triggerScenarios":"Passing ring.EmailAuth{Email: \"x@y.com\"} without Password, or with both fields empty (zero-value struct).","commonSituations":"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.","solutions":["Supply both Email and Password in the EmailAuth struct.","Verify the config/env values feeding these fields are loaded before construction.","Prefer RefreshTokenAuth if you have a refresh token — it is the more stable auth path.","Add a startup validation that trims and checks both fields are non-empty."],"exampleFix":"// before\nauth := ring.EmailAuth{Email: cfg.Email} // password missing\n// after\nif cfg.Email == \"\" || cfg.Password == \"\" {\n    return errors.New(\"ring email auth needs both email and password\")\n}\nauth := ring.EmailAuth{Email: cfg.Email, Password: cfg.Password}","handlingStrategy":"validation","validationCode":"if a.Email == \"\" || a.Password == \"\" { return errors.New(\"ring EmailAuth requires both email and password\") }","typeGuard":null,"tryCatchPattern":"client, err := ring.NewClient(auth)\nif err != nil && strings.Contains(err.Error(), \"email and password are required\") {\n    return fmt.Errorf(\"ring credentials incomplete in config: %w\", err)\n}","preventionTips":["Load email and password from the same config source so they arrive together","Trim whitespace and reject blank-after-trim values at startup","Prefer RefreshTokenAuth to avoid password handling entirely","Add a config linter/test that constructs the client in CI with dummy creds"],"tags":["go","ring","auth","config"],"backgroundTag":"missing-credentials","analyzedSha":"c245815e75e2a5fd60b4290f12bfc04e55a984d3","analyzedAt":"2026-09-07T11:47:02.965Z","contentChangedAt":"2026-09-07T11:47:02.965Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}