calcom/cal.diy · error · HttpError

You must be logged in to do this

Error message

You must be logged in to do this

What it means

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.

Source

Thrown at apps/web/pages/api/integrations/[...args].ts:28

import type { AppDeclarativeHandler, AppHandler } from "@calcom/types/AppHandler";

const defaultIntegrationAddHandler = async ({
  slug,
  supportsMultipleInstalls,
  appType,
  user,
  teamId = undefined,
  createCredential,
}: {
  slug: string;
  supportsMultipleInstalls: boolean;
  appType: string;
  user?: Session["user"];
  teamId?: number;
  createCredential: AppDeclarativeHandler["createCredential"];
}) => {
  if (!user?.id) {
    throw new HttpError({ statusCode: 401, message: "You must be logged in to do this" });
  }
  if (!supportsMultipleInstalls) {
    const alreadyInstalled = await prisma.credential.findFirst({
      where: {
        appId: slug,
        ...(teamId ? { AND: [{ userId: user.id }, { teamId }] } : { userId: user.id }),
      },
    });
    if (alreadyInstalled) {
      throw new Error("App is already installed");
    }
  }

  await throwIfNotHaveAdminAccessToTeam({ teamId: teamId ?? null, userId: user.id });

  await createCredential({ user: user, appType, slug, teamId });
};

View on GitHub (pinned to 176037d0af)

Solutions

  1. Verify the user is still logged in (reload the page / re-authenticate) and retry the install.
  2. Check that NEXTAUTH_SECRET and NEXTAUTH_URL are set correctly in the environment and that getServerSession can decrypt the session cookie.
  3. If behind a reverse proxy, ensure X-Forwarded-Proto and cookie Secure/SameSite settings allow the session cookie through.
  4. Ensure the client sends credentials/cookies with the request (no credentials:'omit').

Example fix

// before: calling fetch without credentials
fetch('/api/integrations/googlecalendar/add');
// after: ensure cookies are sent
fetch('/api/integrations/googlecalendar/add', { credentials: 'include' });
Defensive patterns

Strategy: validation

Validate before calling

import { getServerSession } from '@calcom/features/auth/lib/getServerSession';
// before dispatching to defaultIntegrationAddHandler
const session = await getServerSession({ req });
if (!session?.user?.id) {
  return res.status(401).json({ message: 'You must be logged in to do this' });
}
// safe to proceed with declarative handler install

Type guard

function hasSessionUser(req: NextApiRequest): req is NextApiRequest & { session: { user: { id: number } } } {
  return typeof req.session?.user?.id === 'number';
}

Try / catch

try {
  await defaultIntegrationAddHandler({ user: req.session?.user, ... });
} catch (e) {
  if (e instanceof HttpError && e.statusCode === 401) {
    return res.status(401).json({ message: 'Re-authentication required' });
  }
  throw e;
}

Prevention

When it happens

Trigger: 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).

Common situations: 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.

Related errors


AI-assisted analysis of calcom/cal.diy@176037d0af (2026-08-12). Data as JSON: /api/errors/83a5de9961596c18. Report an issue: GitHub.