{"record":{"id":"83a5de9961596c18","repo":"calcom/cal.diy","slug":"you-must-be-logged-in-to-do-this","errorCode":null,"errorMessage":"You must be logged in to do this","messagePattern":"You must be logged in to do this","errorType":"http","errorClass":"HttpError","httpStatus":401,"severity":"error","filePath":"apps/web/pages/api/integrations/[...args].ts","lineNumber":28,"sourceCode":"import type { AppDeclarativeHandler, AppHandler } from \"@calcom/types/AppHandler\";\n\nconst defaultIntegrationAddHandler = async ({\n  slug,\n  supportsMultipleInstalls,\n  appType,\n  user,\n  teamId = undefined,\n  createCredential,\n}: {\n  slug: string;\n  supportsMultipleInstalls: boolean;\n  appType: string;\n  user?: Session[\"user\"];\n  teamId?: number;\n  createCredential: AppDeclarativeHandler[\"createCredential\"];\n}) => {\n  if (!user?.id) {\n    throw new HttpError({ statusCode: 401, message: \"You must be logged in to do this\" });\n  }\n  if (!supportsMultipleInstalls) {\n    const alreadyInstalled = await prisma.credential.findFirst({\n      where: {\n        appId: slug,\n        ...(teamId ? { AND: [{ userId: user.id }, { teamId }] } : { userId: user.id }),\n      },\n    });\n    if (alreadyInstalled) {\n      throw new Error(\"App is already installed\");\n    }\n  }\n\n  await throwIfNotHaveAdminAccessToTeam({ teamId: teamId ?? null, userId: user.id });\n\n  await createCredential({ user: user, appType, slug, teamId });\n};\n","sourceCodeStart":10,"sourceCodeEnd":46,"githubUrl":"https://github.com/calcom/cal.diy/blob/176037d0afbe572f870a3c702985e7cd83fe6c0c/apps/web/pages/api/integrations/[...args].ts#L10-L46","documentation":"Thrown by defaultIntegrationAddHandler in the integrations catch-all API route when a declarative (non-function) app handler is being installed but the request has no authenticated user id. The route pre-checks auth only for apiEndpoint === 'add' at the top level, so this is the secondary guard inside the credential-creation path for declarative handlers. It surfaces as an HttpError with statusCode 401.","triggerScenarios":"A POST/GET to /api/integrations/<app>/<endpoint> where <endpoint> resolves to a declarative handler object (not a function), req.session is null or req.session.user.id is undefined. This happens when the session cookie expired between page load and the install call, or when getServerSession fails silently (e.g. misconfigured NEXTAUTH_SECRET).","commonSituations":"Session expired while the user sat on the integrations page; NEXTAUTH_SECRET missing or rotated so getServerSession returns null; cookie blocked by SameSite/Secure policy in production behind a proxy; calling the route from a server-side script without forwarding auth cookies.","solutions":["Verify the user is still logged in (reload the page / re-authenticate) and retry the install.","Check that NEXTAUTH_SECRET and NEXTAUTH_URL are set correctly in the environment and that getServerSession can decrypt the session cookie.","If behind a reverse proxy, ensure X-Forwarded-Proto and cookie Secure/SameSite settings allow the session cookie through.","Ensure the client sends credentials/cookies with the request (no credentials:'omit')."],"exampleFix":"// before: calling fetch without credentials\nfetch('/api/integrations/googlecalendar/add');\n// after: ensure cookies are sent\nfetch('/api/integrations/googlecalendar/add', { credentials: 'include' });","handlingStrategy":"validation","validationCode":"import { getServerSession } from '@calcom/features/auth/lib/getServerSession';\n// before dispatching to defaultIntegrationAddHandler\nconst session = await getServerSession({ req });\nif (!session?.user?.id) {\n  return res.status(401).json({ message: 'You must be logged in to do this' });\n}\n// safe to proceed with declarative handler install","typeGuard":"function hasSessionUser(req: NextApiRequest): req is NextApiRequest & { session: { user: { id: number } } } {\n  return typeof req.session?.user?.id === 'number';\n}","tryCatchPattern":"try {\n  await defaultIntegrationAddHandler({ user: req.session?.user, ... });\n} catch (e) {\n  if (e instanceof HttpError && e.statusCode === 401) {\n    return res.status(401).json({ message: 'Re-authentication required' });\n  }\n  throw e;\n}","preventionTips":["Always populate req.session via getServerSession at the top of the route before any handler dispatch.","Make the integrations page re-check auth before allowing an install click.","Send cookies with credentials:'include' on install requests from the client."],"tags":["authentication","session","api","integrations"],"backgroundTag":null,"analyzedSha":"176037d0afbe572f870a3c702985e7cd83fe6c0c","analyzedAt":"2026-08-12T19:12:41.464Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}