{"record":{"id":"05453553f7e61eaf","repo":"wtfutil/wtf","slug":"errors-new-response-errormessage","errorCode":null,"errorMessage":"errors.New(response.ErrorMessage)","messagePattern":"errors\\.New\\(response\\.ErrorMessage\\)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"modules/twitch/widget.go","lineNumber":87,"sourceCode":"\tcase \"followed\":\n\t\tresponse, err = widget.twitch.FollowedStreams(&helix.FollowedStreamsParams{\n\t\t\tUserID: widget.twitch.UserID,\n\t\t})\n\tcase \"top\":\n\t\tresponse, err = widget.twitch.TopStreams(&helix.StreamsParams{\n\t\t\tFirst:      widget.settings.numberOfResults,\n\t\t\tGameIDs:    widget.settings.gameIds,\n\t\t\tLanguage:   widget.settings.languages,\n\t\t\tType:       widget.settings.streamType,\n\t\t\tUserIDs:    widget.settings.userIds,\n\t\t\tUserLogins: widget.settings.userLogins,\n\t\t})\n\t}\n\n\tif err != nil {\n\t\thandleError(widget, err)\n\t} else if response.ErrorMessage != \"\" {\n\t\thandleError(widget, errors.New(response.ErrorMessage))\n\t} else {\n\t\tstreams := makeStreams(response)\n\t\twidget.topStreams = streams\n\t\twidget.err = nil\n\t\tif len(streams) <= widget.settings.numberOfResults {\n\t\t\twidget.SetItemCount(len(widget.topStreams))\n\t\t} else {\n\t\t\twidget.topStreams = streams[:widget.settings.numberOfResults]\n\t\t\twidget.SetItemCount(len(widget.topStreams))\n\t\t}\n\t}\n\n\twidget.Render()\n}\n\nfunc (widget *Widget) Render() {\n\twidget.Redraw(widget.content)\n}","sourceCodeStart":69,"sourceCodeEnd":105,"githubUrl":"https://github.com/wtfutil/wtf/blob/bb838c1ccb0f0f3223690df44afdec663d622881/modules/twitch/widget.go#L69-L105","documentation":"This is not a fixed message: the Twitch widget dynamically builds the error as errors.New(response.ErrorMessage). When the Twitch API response carries a non-empty ErrorMessage (e.g. from the GQL/streams query), Refresh passes it through handleError(widget, errors.New(response.ErrorMessage)) and stores it on the widget instead of populating stream data.","triggerScenarios":"Widget.Refresh() succeeds at the transport level but response.ErrorMessage != \"\" — i.e. the Twitch API returned an application-level error such as invalid client ID, invalid OAuth token, or a query error; the raw message text comes straight from Twitch.","commonSituations":"Expired or revoked Twitch OAuth token; wrong/missing client-id in module settings; Twitch API (GQL) changes or rate limiting; username lookup failing for an invalid channel name.","solutions":["Read the widget's displayed error text — it is Twitch's own message and indicates the precise cause.","Regenerate the OAuth token / re-run the module's authentication step if the message mentions auth or token.","Verify client-id and any username settings in the twitch module configuration.","Retry later or update WTFUtil if the message indicates a GraphQL/schema error (API drift)."],"exampleFix":"// before: token expired, response.ErrorMessage = \"Could not authenticate user\"\n// after: refresh credentials\n// settings.yml\ntwitch:\n  clientID: \"<valid-client-id>\"\n  # re-run auth flow to refresh the token, then restart wtfutil","handlingStrategy":"try-catch","validationCode":"if os.Getenv(\"TWITCH_CLIENT_ID\") == \"\" || token == \"\" {\n    return errors.New(\"Twitch clientID and OAuth token required before refresh\")\n}","typeGuard":null,"tryCatchPattern":"if widget.err != nil {\n    // widget surface shows Twitch's raw ErrorMessage; log and act:\n    log.Printf(\"twitch API error: %v\", widget.err)\n    if strings.Contains(strings.ToLower(widget.err.Error()), \"auth\") {\n        // refresh token / re-authenticate\n    }\n}","preventionTips":["Refresh Twitch OAuth tokens before expiry.","Validate client-id against the Twitch developer console.","Watch for Twitch GQL API changes and keep WTFUtil updated."],"tags":["twitch","api","dynamic-error","authentication"],"backgroundTag":"api-error-response","analyzedSha":"bb838c1ccb0f0f3223690df44afdec663d622881","analyzedAt":"2026-09-03T17:02:45.030Z","contentChangedAt":"2026-09-03T17:02:45.030Z","schemaVersion":2},"datasetVersion":"2026-09-11T00:17:11.886Z"}