{"record":{"id":"fb96de6e70845ffd","repo":"pocketbase/pocketbase","slug":"failed-to-fetch-authuser-data","errorCode":null,"errorMessage":"failed to fetch AuthUser data","messagePattern":"failed to fetch AuthUser data","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"tools/auth/twitch.go","lineNumber":71,"sourceCode":"\tif err := json.Unmarshal(data, &rawUser); err != nil {\n\t\treturn nil, err\n\t}\n\n\textracted := struct {\n\t\tData []struct {\n\t\t\tId              string `json:\"id\"`\n\t\t\tLogin           string `json:\"login\"`\n\t\t\tDisplayName     string `json:\"display_name\"`\n\t\t\tEmail           string `json:\"email\"`\n\t\t\tProfileImageURL string `json:\"profile_image_url\"`\n\t\t} `json:\"data\"`\n\t}{}\n\tif err := json.Unmarshal(data, &extracted); err != nil {\n\t\treturn nil, err\n\t}\n\n\tif len(extracted.Data) == 0 {\n\t\treturn nil, errors.New(\"failed to fetch AuthUser data\")\n\t}\n\n\tuser := &AuthUser{\n\t\tId:           extracted.Data[0].Id,\n\t\tName:         extracted.Data[0].DisplayName,\n\t\tUsername:     extracted.Data[0].Login,\n\t\tEmail:        extracted.Data[0].Email,\n\t\tAvatarURL:    extracted.Data[0].ProfileImageURL,\n\t\tRawUser:      rawUser,\n\t\tAccessToken:  token.AccessToken,\n\t\tRefreshToken: token.RefreshToken,\n\t}\n\n\tuser.Expiry, _ = types.ParseDateTime(token.Expiry)\n\n\treturn user, nil\n}\n","sourceCodeStart":53,"sourceCodeEnd":89,"githubUrl":"https://github.com/pocketbase/pocketbase/blob/5d217ddb50cb144d80a5d0b0bdf11b52b2c3e457/tools/auth/twitch.go#L53-L89","documentation":"Returned by the Twitch provider when the Helix `GET /users` response contains an empty `data` array after a successful token exchange. Twitch returns an empty data array when the access token does not identify a user — most commonly an app access token (client credentials) instead of a user access token, or a token whose user context could not be resolved. PocketBase has no user record to build, so it fails.","triggerScenarios":"Completing the OAuth code exchange with a client-credentials/app token instead of the authorization-code flow; the token request used the wrong client_id (Twitch resolves user context per client); authorization was skipped so no user was attached to the token.","commonSituations":" Mixing up app tokens and user tokens when scripting Twitch integrations; client_id used at token exchange differing from the one used at authorize; sandbox/test setup where the user never actually authorized.","solutions":["Ensure the login uses the authorization code flow (user is redirected and consents), not a client-credentials/app token.","Verify the same Twitch client_id is used for both the authorize URL and the token exchange.","Revoke the stored token and redo the interactive OAuth flow.","Decode/inspect the access token (GET /helix/users with it via curl) to confirm Twitch associates a user with it."],"exampleFix":"# before: app token (no user) -> data: []\ncurl -H 'Client-Id: CID' -H 'Authorization: Bearer APP_TOKEN' https://api.twitch.tv/helix/users\n\n# after: user token from authorization code flow -> data: [{...}]\ncurl -H 'Client-Id: CID' -H 'Authorization: Bearer USER_TOKEN' https://api.twitch.tv/helix/users","handlingStrategy":"validation","validationCode":"// before building the auth flow, assert a user token is being used\n// (authorization-code flow, not client credentials)\nif authMode == \"client_credentials\" {\n    return errors.New(\"Twitch auth requires a user access token (authorization code flow)\")\n}","typeGuard":null,"tryCatchPattern":"user, err := provider.FetchAuthUser(token)\nif err != nil && strings.Contains(err.Error(), \"failed to fetch AuthUser data\") {\n    // discard cached token and restart interactive flow\n    return restartOAuthFlow()","preventionTips":["Use the authorization code flow for user login; reserve app tokens for server-side APIs.","Keep the same client_id for authorize and token exchange steps.","Clear stored tokens when switching Twitch apps to avoid mismatched user context."],"tags":["twitch","auth","oauth","helix-api","go"],"backgroundTag":null,"analyzedSha":"5d217ddb50cb144d80a5d0b0bdf11b52b2c3e457","analyzedAt":"2026-08-15T10:06:33.165Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}