{"record":{"id":"9490770cf9e66547","repo":"mastra-ai/mastra","slug":"failed-to-fetch-user-info-from-clerk","errorCode":null,"errorMessage":"Failed to fetch user info from Clerk","messagePattern":"Failed to fetch user info from Clerk","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"auth/clerk/src/index.ts","lineNumber":594,"sourceCode":"\n      // Get user info — try ID token first, fall back to userinfo endpoint\n      let user: EEUser;\n      if (tokens.id_token) {\n        const payload = await verifyJwks(tokens.id_token, self.jwksUri);\n        user = {\n          id: payload.sub!,\n          email: (payload.email as string) ?? undefined,\n          name: (payload.name as string) ?? undefined,\n          avatarUrl: (payload.picture as string) ?? undefined,\n        };\n      } else {\n        const userInfoResponse = await fetch(`${self.fapiUrl}/oauth/userinfo`, {\n          headers: { Authorization: `Bearer ${tokens.access_token}` },\n          signal: AbortSignal.timeout(10_000), // 10 second timeout\n        });\n\n        if (!userInfoResponse.ok) {\n          throw new Error('Failed to fetch user info from Clerk');\n        }\n\n        const userInfo = (await userInfoResponse.json()) as {\n          sub: string;\n          email?: string;\n          name?: string;\n          picture?: string;\n        };\n        user = {\n          id: userInfo.sub,\n          email: userInfo.email,\n          name: userInfo.name,\n          avatarUrl: userInfo.picture,\n        };\n      }\n\n      // Try to enrich user with full Clerk data\n      try {","sourceCodeStart":576,"sourceCodeEnd":612,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/auth/clerk/src/index.ts#L576-L612","documentation":"With a successfully obtained access token, the provider calls Clerk's `/oauth/userinfo` endpoint (on the FAPI URL) to fetch the user's profile (sub, email, name). If that HTTP response is not ok — token rejected, endpoint unreachable/5xx, scopes missing — the library throws this generic error. Unlike the token-exchange error, the upstream body is discarded, so the message doesn't include the server's reason.","triggerScenarios":"SSO callback reaches the userinfo fetch and `userInfoResponse.ok` is false: access_token rejected by Clerk (revoked/wrong instance), Clerk FAPI returning 5xx, proxy blocking the request, or the 10s AbortSignal.timeout firing (which also manifests as a failed fetch).","commonSituations":"Secret keys from one Clerk instance paired with a FAPI URL from another; Clerk incident/degradation; corporate egress proxy or firewall blocking the call from a serverless function; clock/auth issues causing immediate token invalidation.","solutions":["Log the actual response status (add temporary instrumentation or check server logs) to distinguish 401 (token problem) from 5xx (Clerk problem).","Confirm oauthClientId/secret and fapiUrl all belong to the same Clerk instance; realign them from the Clerk dashboard.","Retry the callback flow — a fresh access token often resolves transient 401/5xx.","Check network egress from your deployment (serverless/VPC) to Clerk's FAPI domain and proxy settings.","Check Clerk status page for an ongoing incident."],"exampleFix":"// before: raw failure to user\nawait provider.handleCallback(url);\n// after\ntry {\n  await provider.handleCallback(url);\n} catch (e) {\n  if ((e as Error).message === 'Failed to fetch user info from Clerk') {\n    return res.redirect('/auth/sso/login'); // re-run flow with fresh token\n  }\n  throw e;\n}","handlingStrategy":"try-catch","validationCode":"async function canReachClerkUserInfo(fapiUrl: string, token: string): Promise<boolean> {\n  try {\n    const r = await fetch(`${fapiUrl}/oauth/userinfo`, {\n      headers: { Authorization: `Bearer ${token}` },\n      signal: AbortSignal.timeout(10_000),\n    });\n    return r.ok;\n  } catch {\n    return false;\n  }\n}","typeGuard":null,"tryCatchPattern":"try {\n  await provider.handleCallback(req.url);\n} catch (e) {\n  if ((e as Error).message === 'Failed to fetch user info from Clerk') {\n    logger.error('Clerk userinfo fetch failed; check token validity, FAPI URL and egress network');\n    return restartLoginFlow();\n  }\n  throw e;\n}","preventionTips":["Keep fapiUrl, secret key and OAuth credentials from the same Clerk instance.","Verify server egress to Clerk's FAPI domain from your deployment environment.","Retry the callback flow once with a fresh token before failing.","Subscribe to Clerk status updates for incident awareness."],"tags":["auth","clerk","oauth","network","userinfo"],"backgroundTag":"userinfo-fetch-failed","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}