{"record":{"id":"3c269899a796366b","repo":"nextauthjs/next-auth","slug":"sendgrid-error-await-res-text","errorCode":null,"errorMessage":"Sendgrid error: + (await res.text())","messagePattern":"Sendgrid error: \\+ \\(await res\\.text\\(\\)\\)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/core/src/providers/sendgrid.ts","lineNumber":32,"sourceCode":"      const { host } = new URL(url)\n      const res = await fetch(\"https://api.sendgrid.com/v3/mail/send\", {\n        method: \"POST\",\n        headers: {\n          Authorization: `Bearer ${provider.apiKey}`,\n          \"Content-Type\": \"application/json\",\n        },\n        body: JSON.stringify({\n          personalizations: [{ to: [{ email: to }] }],\n          from: { email: provider.from },\n          subject: `Sign in to ${host}`,\n          content: [\n            { type: \"text/plain\", value: text({ url, host }) },\n            { type: \"text/html\", value: html({ url, host, theme }) },\n          ],\n        }),\n      })\n      // REVIEW: Clean up error handling\n      if (!res.ok) throw new Error(\"Sendgrid error: \" + (await res.text()))\n    },\n    options: config,\n  }\n}\n","sourceCodeStart":14,"sourceCodeEnd":37,"githubUrl":"https://github.com/nextauthjs/next-auth/blob/a1a16a5a7780488c7449feece410033f445d0b31/packages/core/src/providers/sendgrid.ts#L14-L37","documentation":"The SendGrid email provider in Auth.js throws this error when the SendGrid mail-send API responds with a non-OK status during sendVerificationRequest (the source even carries a 'REVIEW: Clean up error handling' comment). The raw response text — SendGrid's JSON errors array describing each rejection — is appended to the message. It means SendGrid refused the send request.","triggerScenarios":"The fetch to https://api.sendgrid.com/v3/mail/send returns res.ok === false: invalid/missing SENDGRID_API_KEY, 'from' address not a verified sender, request body rejected (validation error), or HTTP 429 for exceeding mail quota. Note SendGrid returns 202 on success with an empty body, so any body text accompanies an error.","commonSituations":"Developers use an API key without 'Mail Send' permission scope, send from an unverified Single Sender or domain, or run on a free tier hitting daily limits. Deployed environments often miss the SENDGRID_API_KEY env var entirely.","solutions":["Read the response text in the error — SendGrid includes a JSON errors array pinpointing the problem.","Verify SENDGRID_API_KEY is set and has Mail Send permission enabled in the SendGrid dashboard.","Verify the 'from' address as a Single Sender or via domain authentication (DNS records).","Check for 403 (scope) vs 401 (bad key) vs 429 (rate limit) codes in the embedded response to pick the right fix."],"exampleFix":"// before\nSendgrid({ apiKey: process.env.SENDGRID_API_KEY, from: \"me@personalmail.com\" }) // unverified sender\n// after\n// Verify sender identity in SendGrid first, then:\nSendgrid({ apiKey: process.env.SENDGRID_API_KEY, from: \"no-reply@verified-domain.com\" })","handlingStrategy":"validation","validationCode":"if (!process.env.SENDGRID_API_KEY) throw new Error(\"SENDGRID_API_KEY is not set\")\n// Confirm the API key has \"Mail Send\" scope enabled in the SendGrid dashboard.","typeGuard":"function isSendGridErrorBody(text: string): boolean {\n  try {\n    const parsed = JSON.parse(text)\n    return Array.isArray(parsed.errors)\n  } catch {\n    return false\n  }\n}","tryCatchPattern":"try {\n  await signIn(\"email\", { email })\n} catch (err) {\n  const text = (err as Error).message.replace(\"Sendgrid error: \", \"\")\n  console.error(\"SendGrid API response:\", text) // JSON errors array\n}","preventionTips":["Grant the API key the Mail Send permission scope.","Verify Single Sender or authenticate the sending domain before production.","Watch for 429 rate limits on free-tier accounts.","Note success is HTTP 202 with empty body; any body means an error."],"tags":["email","http-response","api-key","provider"],"backgroundTag":"email-provider-api-error","analyzedSha":"a1a16a5a7780488c7449feece410033f445d0b31","analyzedAt":"2026-08-28T21:52:38.200Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}