{"record":{"id":"41d4dee687ec2d0f","repo":"AlexxIT/go2rtc","slug":"either-email-password-or-refresh-token-is-required-41d4de","errorCode":null,"errorMessage":"either email/password or refresh token is required","messagePattern":"either email/password or refresh token is required","errorType":"http","errorClass":null,"httpStatus":400,"severity":"warning","filePath":"internal/ring/ring.go","lineNumber":74,"sourceCode":"\t\t}\n\t} else if refreshToken := query.Get(\"refresh_token\"); refreshToken != \"\" {\n\t\t// Refresh Token Flow\n\t\tif refreshToken == \"\" {\n\t\t\thttp.Error(w, \"either email/password or refresh_token is required\", http.StatusBadRequest)\n\t\t\treturn\n\t\t}\n\n\t\tvar err error\n\t\tringAPI, err = ring.NewRestClient(ring.RefreshTokenAuth{\n\t\t\tRefreshToken: refreshToken,\n\t\t}, nil)\n\n\t\tif err != nil {\n\t\t\thttp.Error(w, err.Error(), http.StatusInternalServerError)\n\t\t\treturn\n\t\t}\n\t} else {\n\t\thttp.Error(w, \"either email/password or refresh token is required\", http.StatusBadRequest)\n\t\treturn\n\t}\n\n\tdevices, err := ringAPI.FetchRingDevices()\n\tif err != nil {\n\t\thttp.Error(w, err.Error(), http.StatusInternalServerError)\n\t\treturn\n\t}\n\n\tcleanQuery := url.Values{}\n\tcleanQuery.Set(\"refresh_token\", ringAPI.RefreshToken)\n\n\tvar items []*api.Source\n\tfor _, camera := range devices.AllCameras {\n\t\tcleanQuery.Set(\"camera_id\", fmt.Sprint(camera.ID))\n\t\tcleanQuery.Set(\"device_id\", camera.DeviceID)\n\n\t\t// Stream source","sourceCodeStart":56,"sourceCodeEnd":92,"githubUrl":"https://github.com/AlexxIT/go2rtc/blob/c245815e75e2a5fd60b4290f12bfc04e55a984d3/internal/ring/ring.go#L56-L92","documentation":"The ring API handler requires credentials to construct a Ring client, but the request contained neither email/password nor a refresh token. The handler returns HTTP 400 with this static message to tell the caller which parameters are mandatory.","triggerScenarios":"POST to the ring endpoint with an empty body or only unrelated form fields, so both the email/password branch and the refresh_token branch are skipped and the else clause fires.","commonSituations":"Client forgot the form fields; field name mismatch (e.g. sending refresh-token instead of refresh_token); curl call without -d parameters; frontend form submitted empty.","solutions":["Send either email+password or refresh_token in the request","Fix the form field names to match what the handler reads","Add client-side validation that blocks submission when both are empty"],"exampleFix":"// before\ncurl -X POST http://host/api/ring\n// after\ncurl -X POST http://host/api/ring -d 'refresh_token=YOUR_TOKEN'","handlingStrategy":"validation","validationCode":"func hasRingCredentials(email, password, refreshToken string) bool {\n\treturn (email != \"\" && password != \"\") || refreshToken != \"\"\n}\nif !hasRingCredentials(email, password, refreshToken) { /* return 400 before calling the API */ }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always send either email+password or refresh_token","Match form field names exactly to the handler's expectations","Validate required fields in the client before submission","Document the required parameters in your API client wrapper"],"tags":["go","http","validation","missing-parameters"],"backgroundTag":"missing-required-argument","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"}