{"record":{"id":"cff8a433b9d395ca","repo":"mastra-ai/mastra","slug":"oauth-failed-tokendata-error","errorCode":null,"errorMessage":"OAuth failed: ${tokenData.error}","messagePattern":"OAuth failed: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"channels/slack/src/provider.ts","lineNumber":1436,"sourceCode":"          redirect_uri: `${baseUrl}/slack/oauth/callback`,\n        }),\n        signal: AbortSignal.timeout(30_000),\n      });\n\n      if (!tokenResponse.ok) {\n        throw new Error(`Slack OAuth HTTP error: ${tokenResponse.status} ${tokenResponse.statusText}`);\n      }\n\n      const tokenData = (await tokenResponse.json()) as {\n        ok: boolean;\n        error?: string;\n        access_token?: string;\n        bot_user_id?: string;\n        team?: { id: string; name: string };\n      };\n\n      if (!tokenData.ok) {\n        throw new Error(`OAuth failed: ${tokenData.error}`);\n      }\n\n      if (!tokenData.access_token || !tokenData.bot_user_id || !tokenData.team?.id) {\n        throw new Error('Slack OAuth response missing required fields (access_token, bot_user_id, or team)');\n      }\n\n      // Save completed installation (encrypted)\n      const installation: SlackInstallation = {\n        id: pending.id,\n        agentId: pending.agentId,\n        ownerType: pending.ownerType ?? 'agent',\n        webhookId: pending.webhookId,\n        appId: pending.appId,\n        clientId: pending.clientId,\n        clientSecret: pending.clientSecret,\n        signingSecret: pending.signingSecret,\n        botToken: tokenData.access_token,\n        botUserId: tokenData.bot_user_id,","sourceCodeStart":1418,"sourceCodeEnd":1454,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/channels/slack/src/provider.ts#L1418-L1454","documentation":"Slack's oauth.v2.access responded HTTP 200 but with ok:false and an error code (e.g. invalid_code, code_already_used, redirect_uri_mismatch, bad_client_secret). The provider throws the Slack-provided error code so the developer can diagnose the OAuth rejection directly.","triggerScenarios":"Completing the OAuth callback when Slack rejects the grant: code already redeemed, code expired (>10 min), redirect_uri differing from the initial authorize request, or wrong app credentials.","commonSituations":"Users double-clicking the authorize button or refreshing the callback URL (code_already_used); mismatched redirect URLs between local dev (http://localhost) and the Slack app config; stale client secret after rotating credentials.","solutions":["Restart the OAuth flow from the beginning to obtain a fresh code (codes are single-use and short-lived).","Ensure redirect_uri in the token exchange exactly matches the redirect URL registered in the Slack app settings.","Verify SLACK_CLIENT_ID/SLACK_CLIENT_SECRET are current and correct (the error code often says bad_client_secret).","Read the interpolated Slack error code (e.g. invalid_code) and address it specifically."],"exampleFix":"// before\nredirect_uri: `${baseUrl}/slack/oauth/callback` // must match Slack app config\n// after\n// In Slack app settings > OAuth & Permissions, add exactly:\n//   https://<your-baseUrl>/slack/oauth/callback\n// then restart the install flow (do not reuse the code).","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  await handleSlackOAuthCallback(req);\n} catch (e) {\n  const m = /OAuth failed: (.+)/.exec(e.message);\n  if (m) {\n    // e.g. code_already_used / invalid_code / redirect_uri_mismatch\n    return restartOAuthFlow(m[1]);\n  }\n  throw e;\n}","preventionTips":["Treat OAuth codes as single-use: never retry the callback with the same code.","Keep the redirect_uri byte-identical between authorize and token exchange and Slack app settings.","Rotate client secrets centrally so all environments update together."],"tags":["slack","oauth","authorization"],"backgroundTag":"oauth-error","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}