{"record":{"id":"e4ac7f20513d14ac","repo":"calcom/cal.diy","slug":"user-either-already-has-booking-at-this-time-or-is","errorCode":null,"errorMessage":"User either already has booking at this time or is not available","messagePattern":"User either already has booking at this time or is not available","errorType":"exception","errorClass":"BadRequestException","httpStatus":400,"severity":"error","filePath":"apps/api/v2/src/platform/bookings/2024-08-13/services/errors.service.ts","lineNumber":42,"sourceCode":"      );\n    }\n    if (body.teamSlug && body.eventTypeSlug && body.organizationSlug) {\n      throw new NotFoundException(\n        `Event type with slug ${body.eventTypeSlug} belonging to team ${body.teamSlug} within organization ${body.organizationSlug} not found.`\n      );\n    }\n    throw new NotFoundException(`Event type with id ${body.eventTypeId} not found.`);\n  }\n\n  handleBookingError(error: unknown, bookingTeamEventType: boolean): never {\n    const hostsUnavaile = \"One of the hosts either already has booking at this time or is not available\";\n\n    if (error instanceof Error) {\n      if (error.message === \"no_available_users_found_error\") {\n        if (bookingTeamEventType) {\n          throw new BadRequestException(hostsUnavaile);\n        }\n        throw new BadRequestException(\"User either already has booking at this time or is not available\");\n      } else if (error.message === \"booking_time_out_of_bounds_error\") {\n        throw new BadRequestException(\n          `The event type can't be booked at the \"start\" time provided. This could be because it's too soon (violating the minimum booking notice) or too far in the future (outside the event's scheduling window). Try fetching available slots first using the GET /v2/slots endpoint and then make a booking with \"start\" time equal to one of the available slots.`\n        );\n      } else if (error.message === \"Attempting to book a meeting in the past.\") {\n        throw new BadRequestException(\"Attempting to book a meeting in the past.\");\n      } else if (error.message === \"hosts_unavailable_for_booking\") {\n        throw new BadRequestException(hostsUnavaile);\n      } else if (error.message === \"booker_limit_exceeded_error\") {\n        throw new BadRequestException(\n          \"Attendee with this email can't book because the maximum number of active bookings has been reached.\"\n        );\n      } else if (error.message === \"booker_limit_exceeded_error_reschedule\") {\n        const errorData =\n          \"data\" in error ? (error.data as { rescheduleUid: string }) : { rescheduleUid: undefined };\n        let message =\n          \"Attendee with this email can't book because the maximum number of active bookings has been reached.\";\n        if (errorData?.rescheduleUid) {","sourceCodeStart":24,"sourceCodeEnd":60,"githubUrl":"https://github.com/calcom/cal.diy/blob/176037d0afbe572f870a3c702985e7cd83fe6c0c/apps/api/v2/src/platform/bookings/2024-08-13/services/errors.service.ts#L24-L60","documentation":"Thrown by handleBookingError when the booking engine raised 'no_available_users_found_error' and bookingTeamEventType is false. BadRequestException (HTTP 400). The single-user variant of error 326: the organizer already has a booking at that time or is outside their working hours.","triggerScenarios":"Booking a user (non-team) event type at a start time where the owner already has a booking, has blocked their calendar, is outside working hours, or has a conflicting buffer. The engine returns no_available_users_found_error and the service maps it to this single-user message.","commonSituations":"Double-booking the same slot from two clients; booking outside the user's set working hours; overlapping buffers; user manually blocked the slot in their calendar; timezone math error producing a slot inside a busy period.","solutions":["Pre-fetch available slots via GET /v2/slots and POST a start time returned by it.","Verify the attendee's timezone matches the slot timezone to avoid off-by-one double bookings.","Retry with the next available slot rather than the rejected one.","Reduce booking buffer overlap by adjusting event-type buffers if the pattern recurs."],"exampleFix":"// before\nstart = '2026-08-12T15:00:00Z'  // owner busy\n\n// after\nconst slots = await api.get(`/v2/slots?eventTypeId=${eventTypeId}&startTime=2026-08-12T00:00:00Z&endTime=2026-08-13T00:00:00Z`);\nstart = slots.data.slots.find(s => s.start !== rejectedStart).start;","handlingStrategy":"validation","validationCode":"const slots = await api.get(`/v2/slots?eventTypeId=${eventTypeId}&startTime=${from}&endTime=${to}`);\nconst ok = slots.data.slots.some(s => s.start === body.start);\nif (!ok) throw new Error('owner not available at requested start');","typeGuard":"null","tryCatchPattern":"try { await api.post('/v2/bookings', body); }\ncatch (e) {\n  if (e.response?.status === 400 && /User either already has booking/.test(e.response.data.message)) {\n    body.start = (await api.get(`/v2/slots?eventTypeId=${body.eventTypeId}&...`)).data.slots[0].start;\n    await api.post('/v2/bookings', body);\n  } else throw e;\n}","preventionTips":["Book only start times returned by GET /v2/slots.","Align attendee timezone with slot timezone to avoid off-by-one double bookings.","Reduce conflicting buffers on the event type."],"tags":["api","bookings","availability","scheduling","nestjs"],"backgroundTag":null,"analyzedSha":"176037d0afbe572f870a3c702985e7cd83fe6c0c","analyzedAt":"2026-08-12T19:12:41.464Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}