{"record":{"id":"bfe56d305e3ac1b4","repo":"calcom/cal.diy","slug":"bookings-can-only-be-marked-as-absent-after-their","errorCode":null,"errorMessage":"Bookings can only be marked as absent after their scheduled start time. Current time in UTC+0: ${nowUtc.toISO()}, Booking start time in UTC+0: ${bookingStartTimeUtc.toISO()}","messagePattern":"Bookings can only be marked as absent after their scheduled start time\\. Current time in UTC\\+0: (.+?), Booking start time in UTC\\+0: (.+?)","errorType":"exception","errorClass":"BadRequestException","httpStatus":400,"severity":"error","filePath":"apps/api/v2/src/platform/bookings/2024-08-13/services/bookings.service.ts","lineNumber":963,"sourceCode":"\n  async markAbsent(\n    bookingUid: string,\n    bookingOwnerId: number,\n    body: MarkAbsentBookingInput_2024_08_13,\n    userUuid: string\n  ) {\n    const bodyTransformed = this.inputService.transformInputMarkAbsentBooking(body);\n    const bookingBefore = await this.bookingsRepository.getByUid(bookingUid);\n\n    if (!bookingBefore) {\n      throw new NotFoundException(`Booking with uid=${bookingUid} not found.`);\n    }\n\n    const nowUtc = DateTime.utc();\n    const bookingStartTimeUtc = DateTime.fromJSDate(bookingBefore.startTime, { zone: \"utc\" });\n\n    if (nowUtc < bookingStartTimeUtc) {\n      throw new BadRequestException(\n        `Bookings can only be marked as absent after their scheduled start time. Current time in UTC+0: ${nowUtc.toISO()}, Booking start time in UTC+0: ${bookingStartTimeUtc.toISO()}`\n      );\n    }\n\n    const platformClientParams = bookingBefore?.eventTypeId\n      ? await this.platformBookingsService.getOAuthClientParams(bookingBefore.eventTypeId)\n      : undefined;\n\n    await handleMarkNoShow({\n      bookingUid,\n      attendees: bodyTransformed.attendees,\n      noShowHost: bodyTransformed.noShowHost,\n      userId: bookingOwnerId,\n      platformClientParams,\n    });\n\n    const booking = await this.bookingsRepository.getByUidWithAttendeesAndUserAndEvent(bookingUid);\n","sourceCodeStart":945,"sourceCodeEnd":981,"githubUrl":"https://github.com/calcom/cal.diy/blob/176037d0afbe572f870a3c702985e7cd83fe6c0c/apps/api/v2/src/platform/bookings/2024-08-13/services/bookings.service.ts#L945-L981","documentation":"Thrown by markAbsent when the current UTC time is before the booking's start time. A booking can only be marked absent (no-show) after its scheduled start has passed. BadRequestException (HTTP 400) includes both timestamps for debugging.","triggerScenarios":"Calling markAbsent on a future booking — e.g. immediately after creation or before the meeting time. The guard compares DateTime.utc() < bookingStartTimeUtc.","commonSituations":"Automated no-show processing triggered too early; timezone confusion causing premature calls; webhook firing on booking creation instead of completion.","solutions":["Schedule the markAbsent call for after the booking end time (e.g. via a delayed job).","Compare local time to booking.startTime before calling and skip if in the future.","Trigger from a post-event webhook rather than a creation webhook."],"exampleFix":"// before\nawait client.post(`/v2/bookings/${uid}/mark-absent`, body);\n// after\nconst b = await client.get(`/v2/bookings/${uid}`);\nif (new Date() > new Date(b.startTime)) {\n  await client.post(`/v2/bookings/${uid}/mark-absent`, body);\n}","handlingStrategy":"validation","validationCode":"const b = await client.get(`/v2/bookings/${uid}`);\nif (new Date().getTime() < new Date(b.startTime).getTime()) throw new Error('Cannot mark absent before start time');","typeGuard":"function isPastStart(startTime: string): boolean {\n  return Date.now() >= new Date(startTime).getTime();\n}","tryCatchPattern":"try { await client.post(`/v2/bookings/${uid}/mark-absent`, body); }\ncatch (e) {\n  if (e.status === 400 && /after their scheduled start time/i.test(e.message)) { /* reschedule for later */ }\n  else throw e;\n}","preventionTips":["Trigger markAbsent from post-event webhooks","Schedule no-show jobs after booking end time","Compare current UTC to booking startTime before calling"],"tags":["api-v2","bookings","absent","timing","validation"],"backgroundTag":null,"analyzedSha":"176037d0afbe572f870a3c702985e7cd83fe6c0c","analyzedAt":"2026-08-12T19:12:41.464Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}