{"record":{"id":"6b1701bd68e88c2c","repo":"calcom/cal.diy","slug":"session-user-must-have-an-email-6b1701","errorCode":null,"errorMessage":"Session user must have an email","messagePattern":"Session user must have an email","errorType":"http","errorClass":"HttpError","httpStatus":400,"severity":"error","filePath":"packages/app-store/googlecalendar/api/add.ts","lineNumber":22,"sourceCode":"import { GOOGLE_CALENDAR_SCOPES, SCOPE_USERINFO_PROFILE, WEBAPP_URL_FOR_OAUTH } from \"@calcom/lib/constants\";\nimport { HttpError } from \"@calcom/lib/http-error\";\nimport { defaultHandler } from \"@calcom/lib/server/defaultHandler\";\nimport { defaultResponder } from \"@calcom/lib/server/defaultResponder\";\n\nimport { encodeOAuthState } from \"../../_utils/oauth/encodeOAuthState\";\nimport { getGoogleAppKeys } from \"../lib/getGoogleAppKeys\";\n\nasync function getHandler(req: NextApiRequest, res: NextApiResponse) {\n  const loggedInUser = req.session?.user;\n\n  if (!loggedInUser) {\n    throw new HttpError({ statusCode: 401, message: \"You must be logged in to do this\" });\n  }\n\n  // Ideally this should never happen, as email is there in session user but typings aren't accurate it seems\n  // TODO: So, confirm and later fix the typings\n  if (!loggedInUser.email) {\n    throw new HttpError({ statusCode: 400, message: \"Session user must have an email\" });\n  }\n\n  const { client_id, client_secret } = await getGoogleAppKeys();\n  const redirect_uri = `${WEBAPP_URL_FOR_OAUTH}/api/integrations/googlecalendar/callback`;\n  const oAuth2Client = new OAuth2Client(client_id, client_secret, redirect_uri);\n\n  const authUrl = oAuth2Client.generateAuthUrl({\n    access_type: \"offline\",\n    scope: [SCOPE_USERINFO_PROFILE, ...GOOGLE_CALENDAR_SCOPES],\n    // A refresh token is only returned the first time the user\n    // consents to providing access.  For illustration purposes,\n    // setting the prompt to 'consent' will force this consent\n    // every time, forcing a refresh_token to be returned.\n    prompt: \"consent\",\n    state: encodeOAuthState(req),\n  });\n\n  res.status(200).json({ url: authUrl });","sourceCodeStart":4,"sourceCodeEnd":40,"githubUrl":"https://github.com/calcom/cal.diy/blob/176037d0afbe572f870a3c702985e7cd83fe6c0c/packages/app-store/googlecalendar/api/add.ts#L4-L40","documentation":"Defensive guard — the source comment states this \"should never happen\" because email is part of the session user, but the typings are loose so it is checked explicitly. Fires `HttpError` **400** when a session user exists but has no `email`. It signals a data-integrity or typing gap rather than normal user input.","triggerScenarios":"A logged-in session whose user object lacks `email` — e.g. the underlying `users` row has null/empty email (legacy/migrated data, or email removed post-signup) yet a session was still issued for that user.","commonSituations":"Migrated/seeded users with no email; sessions created before email became required; an email-change/cleanup flow that nulled email; session typing that marks `email` optional while the code assumes it is present.","solutions":["Ensure the user record has a non-empty email before they reach the integration-install flow (require email at signup/profile).","Fix the session user type so `email` is required, making this guard provably redundant.","If hit, have the affected user complete/update their profile email, then retry the Google install."],"exampleFix":null,"handlingStrategy":"type-guard","validationCode":null,"typeGuard":"// Narrow the session user to one guaranteed to have an email before proceeding\nimport type { Session } from \"next-auth\";\n\nfunction hasEmail(user: Session[\"user\"] | undefined): user is { email: string } & NonNullable<Session[\"user\"]> {\n  return !!user && typeof user.email === \"string\" && user.email.trim().length > 0;\n}\n\n// usage:\nif (!hasEmail(req.session?.user)) {\n  // prompt profile completion instead of reaching the 400 in add.ts\n}","tryCatchPattern":null,"preventionTips":["Require email at signup and on profile save so no session can exist without one.","Tighten the session user type to make `email` required, eliminating the need for the guard.","Run a data check for users with null/empty emails and remediate before they hit integrations."],"tags":["app-store","googlecalendar","session","data-integrity","http-400"],"backgroundTag":null,"analyzedSha":"176037d0afbe572f870a3c702985e7cd83fe6c0c","analyzedAt":"2026-08-12T19:12:41.464Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}