{"record":{"id":"de8ffbe480d1744d","repo":"glanceapp/glance","slug":"fetching-new-app-access-token-v","errorCode":null,"errorMessage":"fetching new app access token: %v","messagePattern":"fetching new app access token: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/glance/widget-reddit.go","lineNumber":185,"sourceCode":"func (widget *redditWidget) fetchSubredditPosts() (forumPostList, error) {\n\tvar client requestDoer = redditHTTPClient\n\tvar baseURL string\n\tvar requestURL string\n\tvar headers http.Header\n\tquery := url.Values{}\n\tapp := &widget.AppAuth\n\n\tif !app.enabled {\n\t\tbaseURL = \"https://www.reddit.com\"\n\t\theaders = http.Header{\n\t\t\t\"User-Agent\": []string{getBrowserUserAgentHeader()},\n\t\t}\n\t} else {\n\t\tbaseURL = \"https://oauth.reddit.com\"\n\n\t\tif app.accessToken == \"\" || time.Now().Add(time.Minute).After(app.tokenExpiresAt) {\n\t\t\tif err := widget.fetchNewAppAccessToken(); err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"fetching new app access token: %v\", err)\n\t\t\t}\n\t\t}\n\n\t\theaders = http.Header{\n\t\t\t\"Authorization\": []string{\"Bearer \" + app.accessToken},\n\t\t\t\"User-Agent\":    []string{app.Name + \"/1.0\"},\n\t\t}\n\t}\n\n\tif widget.Limit > 25 {\n\t\tquery.Set(\"limit\", strconv.Itoa(widget.Limit))\n\t}\n\n\tif widget.Search != \"\" {\n\t\tquery.Set(\"q\", widget.Search+\" subreddit:\"+widget.Subreddit)\n\t\tquery.Set(\"sort\", widget.SortBy)\n\t\trequestURL = fmt.Sprintf(\"%s/search.json?%s\", baseURL, query.Encode())\n\t} else {","sourceCodeStart":167,"sourceCodeEnd":203,"githubUrl":"https://github.com/glanceapp/glance/blob/91324e8de762702e97b0ac5c8e36271d644d8642/internal/glance/widget-reddit.go#L167-L203","documentation":"The Reddit widget uses app-only OAuth (client credentials) against oauth.reddit.com, and refreshing the access token failed. The error wraps the result of fetchNewAppAccessToken, which covers request creation, the token POST, non-200 responses, and response decoding — inspect the wrapped message for the specific stage.","triggerScenarios":"Invalid app client ID/secret (Reddit returns 401), missing or default app-auth config, network failure reaching www.reddit.com/api/v1/access_token, or a non-JSON/failed decode of the token response.","commonSituations":"Wrong client-id/client-secret in the widget config; Reddit app credentials rotated or revoked; egress to reddit.com blocked; system clock skew; token refresh racing on many widgets at once.","solutions":["Read the wrapped error after 'fetching new app access token:' to identify the stage","Verify the app-auth client-id and client-secret match a Reddit 'installed app'/'script' app","Test the credential directly: curl -u <id>:<secret> -d 'grant_type=client_credentials' https://www.reddit.com/api/v1/access_token","Confirm egress/DNS to reddit.com from the glance host"],"exampleFix":"# before\n  subreddit: programming\n  app-access-token:\n    client-id: wrong\n    client-secret: wrong\n# after\n  subreddit: programming\n  app-access-token:\n    client-id: <your-app-id>\n    client-secret: <your-app-secret>","handlingStrategy":"try-catch","validationCode":"if app.ID == \"\" || app.Secret == \"\" {\n    return errors.New(\"app-access-token requires client-id and client-secret\")\n}","typeGuard":null,"tryCatchPattern":"if err := widget.fetchNewAppAccessToken(); err != nil {\n    // fall back to unauthenticated www.reddit.com for this cycle\n    slog.Warn(\"reddit app auth failed, falling back to public API\", \"error\", err)\n    widget.AppAuth.enabled = false // for this fetch\n}","preventionTips":["Validate client-id/client-secret are non-empty at config load","Smoke-test credentials with a curl token request during deployment","Rotate Reddit secrets with a single glance restart to avoid stale tokens"],"tags":["reddit","oauth","authentication","credentials"],"backgroundTag":null,"analyzedSha":"91324e8de762702e97b0ac5c8e36271d644d8642","analyzedAt":"2026-08-15T14:12:54.279Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}