calcom/cal.diy · error · HttpError

Not authenticated

Error message

Not authenticated

What it means

Thrown by authMiddleware in /api/availability/calendar (HttpError, HTTP 401) when getServerSession returns no session or session.user.id. It is the first auth gate: the request carried no valid (or expired) session cookie, so the caller is anonymous.

Solutions

  1. Ensure the client is authenticated (redirect to login) before calling the endpoint.
  2. Send credentials with the request (credentials: 'include' / same-origin fetch).
  3. On 401, refresh the session / re-authenticate and retry once.

Example fix

// before
await fetch('/api/availability/calendar'); // no credentials

// after
const res = await fetch('/api/availability/calendar', { credentials: 'include' });
if (res.status === 401) { router.push('/auth/login'); return; }
Defensive patterns

Strategy: validation

Validate before calling

// Ensure a session exists before calling the endpoint
const session = await getSession();
if (!session?.user?.id) {
  router.push('/auth/login');
  return;
}
await fetch('/api/availability/calendar', { credentials: 'include' });

Type guard

function hasSessionUserId(s: unknown): s is { user: { id: number } } {
  return !!s && typeof s === 'object' &&
    typeof (s as any).user?.id === 'number';
}

Try / catch

try {
  await fetch('/api/availability/calendar', { credentials: 'include' });
} catch (e) {
  if (e instanceof HttpError && e.statusCode === 401) {
    router.push('/auth/login');
    return;
  }
  throw e;
}

Prevention

When it happens

Trigger: GET/POST /api/availability/calendar with no session cookie, an expired session, or a request from a logged-out client (e.g. a background fetch after session timeout).

Common situations: Session cookie expired, third-party cookie blocking, fetch without credentials:'include', user logged out in another tab.

Understand the failure class

Related errors


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

Appendix: source

Thrown at apps/web/app/api/availability/calendar/route.ts:32

import notEmpty from "@calcom/lib/notEmpty";
import { SelectedCalendarRepository } from "@calcom/features/selectedCalendar/repositories/SelectedCalendarRepository";
import prisma from "@calcom/prisma";

import { buildLegacyRequest } from "@lib/buildLegacyCtx";

const selectedCalendarSelectSchema = z.object({
  integration: z.string(),
  externalId: z.string(),
  credentialId: z.coerce.number(),
  delegationCredentialId: z.string().nullish().default(null),
  eventTypeId: z.coerce.number().nullish(),
});

async function authMiddleware() {
  const session = await getServerSession({ req: buildLegacyRequest(await headers(), await cookies()) });

  if (!session?.user?.id) {
    throw new HttpError({ statusCode: 401, message: "Not authenticated" });
  }

  const userRepo = new UserRepository(prisma);
  const userWithCredentials = await userRepo.findUserWithCredentials({
    id: session.user.id,
  });

  if (!userWithCredentials) {
    throw new HttpError({ statusCode: 401, message: "Not authenticated" });
  }

  return userWithCredentials;
}

// TODO: It doesn't seem to be used from within the app. It is possible that someone outside Cal.diy is using this GET endpoint
async function getHandler() {
  const user = await authMiddleware();

View on GitHub (pinned to 176037d0af)