{"record":{"id":"c4e3cbf92df33684","repo":"AlexxIT/go2rtc","slug":"nest-wrong-status-res-status","errorCode":null,"errorMessage":"nest: wrong status: ${res.Status}","messagePattern":"nest: wrong status: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/nest/api.go","lineNumber":71,"sourceCode":"\t\treturn api, nil\n\t}\n\n\tdata := url.Values{\n\t\t\"grant_type\":    []string{\"refresh_token\"},\n\t\t\"client_id\":     []string{clientID},\n\t\t\"client_secret\": []string{clientSecret},\n\t\t\"refresh_token\": []string{refreshToken},\n\t}\n\n\tclient := &http.Client{Timeout: time.Second * 5000}\n\tres, err := client.PostForm(\"https://www.googleapis.com/oauth2/v4/token\", data)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdefer res.Body.Close()\n\n\tif res.StatusCode != 200 {\n\t\treturn nil, errors.New(\"nest: wrong status: \" + res.Status)\n\t}\n\n\tvar resv struct {\n\t\tAccessToken string        `json:\"access_token\"`\n\t\tExpiresIn   time.Duration `json:\"expires_in\"`\n\t\tScope       string        `json:\"scope\"`\n\t\tTokenType   string        `json:\"token_type\"`\n\t}\n\n\tif err = json.NewDecoder(res.Body).Decode(&resv); err != nil {\n\t\treturn nil, err\n\t}\n\n\tapi := &API{\n\t\tToken:     resv.AccessToken,\n\t\tExpiresAt: now.Add(resv.ExpiresIn * time.Second),\n\t}\n","sourceCodeStart":53,"sourceCodeEnd":89,"githubUrl":"https://github.com/AlexxIT/go2rtc/blob/c245815e75e2a5fd60b4290f12bfc04e55a984d3/pkg/nest/api.go#L53-L89","documentation":"NewAPI exchanges credentials with the Nest service for an access token and requires HTTP 200. Any non-200 response aborts API construction with the server's status line embedded in the error. This means the token request itself failed (bad credentials, expired refresh token, or service problem).","triggerScenarios":"Calling nest.NewAPI directly, or indirectly via refreshToken and Dial; the token endpoint returns a status other than 200 (commonly 400/401 for bad or expired tokens).","commonSituations":"Expired or revoked Nest refresh token; wrong client ID/secret in config; Nest/Google cloud outage; token revoked because the user re-authorized the integration elsewhere.","solutions":["Re-run the Nest OAuth flow to obtain fresh access/refresh tokens and update configuration.","Verify client ID, client secret, and token URL in the API configuration.","Check the Nest service status page for outages, then retry with backoff.","Inspect the response body (via a proxy/log) for the OAuth error code (invalid_grant etc.) to confirm the cause."],"exampleFix":"// before\napi, err := nest.NewAPI(ctx, staleRefreshToken)\n\n// after\n// re-authenticate to get a new refresh token\nrefreshToken := runOAuthFlow(clientID, clientSecret)\napi, err := nest.NewAPI(ctx, refreshToken)","handlingStrategy":"try-catch","validationCode":"// check token/credentials shape before calling NewAPI\nif refreshToken == \"\" {\n    return errors.New(\"missing Nest refresh token; run OAuth flow first\")\n}","typeGuard":null,"tryCatchPattern":"api, err := nest.NewAPI(ctx, refreshToken)\nif err != nil {\n    if strings.Contains(err.Error(), \"wrong status\") {\n        // token rejected: trigger full re-auth flow\n        return triggerReauthentication(err)\n    }\n    return err\n}","preventionTips":["Store refresh tokens securely and rotate them per the OAuth provider's policy.","Handle invalid_grant by prompting the user to re-consent instead of retrying forever.","Monitor Nest/Google service status before blaming local config.","Log the HTTP status (not secrets) on token failures for faster diagnosis."],"tags":["nest","http","oauth","token"],"backgroundTag":"oauth-token-exchange-failed","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"}