{"record":{"id":"0079a2a450c384da","repo":"calcom/cal.diy","slug":"booking-location-with-type-inputbookinglocation","errorCode":null,"errorMessage":"Booking location with type ${inputBookingLocation.type} not valid for event type with id=${dbEventType.id}. The event type has following location types: ${allowedLocationTypes.join(\", \")}, and only these types are allowed for booking location.","messagePattern":"Booking location with type (.+?) not valid for event type with id=(.+?)\\. The event type has following location types: (.+?), and only these types are allowed for booking location\\.","errorType":"exception","errorClass":"BadRequestException","httpStatus":400,"severity":"error","filePath":"apps/api/v2/src/platform/bookings/2024-08-13/services/input.service.ts","lineNumber":391,"sourceCode":"      `Booking location with type ${(location as BookingInputLocation_2024_08_13).type} not valid.`\n    );\n  }\n\n  private isBookingLocationWithEventTypeLocations(\n    inputBookingLocation: undefined | string | BookingInputLocation_2024_08_13,\n    dbEventType: EventType\n  ) {\n    if (!inputBookingLocation || typeof inputBookingLocation === \"string\") {\n      // note(Lauris): for backwards compatibility because we had string locations before so let them pass.\n      return true;\n    }\n\n    const eventTypeLocations = this.outputEventTypesService.transformLocations(dbEventType.locations);\n    const allowedLocationTypes = eventTypeLocations.map((location) => location.type);\n\n    const isAllowed = allowedLocationTypes.includes(inputBookingLocation.type);\n    if (!isAllowed) {\n      throw new BadRequestException(\n        `Booking location with type ${inputBookingLocation.type} not valid for event type with id=${\n          dbEventType.id\n        }. The event type has following location types: ${allowedLocationTypes.join(\n          \", \"\n        )}, and only these types are allowed for booking location.`\n      );\n    }\n\n    if (inputBookingLocation.type === \"integration\" && \"integration\" in inputBookingLocation) {\n      const allowedIntegrations = eventTypeLocations\n        .filter((location) => location.type === \"integration\")\n        .map((location) => location.integration);\n\n      const isAllowedIntegration = allowedIntegrations.includes(inputBookingLocation.integration);\n      if (!isAllowedIntegration) {\n        throw new BadRequestException(\n          `Booking location with integration ${\n            inputBookingLocation.integration","sourceCodeStart":373,"sourceCodeEnd":409,"githubUrl":"https://github.com/calcom/cal.diy/blob/176037d0afbe572f870a3c702985e7cd83fe6c0c/apps/api/v2/src/platform/bookings/2024-08-13/services/input.service.ts#L373-L409","documentation":"Thrown by isBookingLocationWithEventTypeLocations when the booking location's type is not among the event type's configured location types. BadRequestException (HTTP 400). The event type's locations are transformed to their API types and the booking location type must appear in that list; otherwise the booking would select a location the organizer did not enable.","triggerScenarios":"POST /v2/bookings with a location object whose type (e.g. 'attendeePhone') is not in the event type's allowed location types (e.g. the event type only allows 'address' and 'integration'). The validator computes allowedLocationTypes from the event type and rejects mismatches. String locations are allowed for backwards compatibility and skip this check.","commonSituations":"Client offers a location type the organizer never enabled on the event type; event type's locations were edited after the client cached them; mismatched expectations between embed config and event type; sending an integration location when only in-person is configured.","solutions":["Fetch GET /v2/event-types/{id} and read its locations to learn which type values are allowed.","Send a location object whose type is in that list (or send a string location for backwards compatibility).","Update the event type in the dashboard to enable the desired location type if the booker needs it.","Validate the location type client-side against the fetched event type before POSTing."],"exampleFix":"// before\nlocation: { type: 'attendeePhone', phone: '+1...' }  // event type only allows ['address','integration']\n\n// after\nconst et = await api.get(`/v2/event-types/${eventTypeId}`);\nconst allowed = et.data.locations.map(l => l.type);\nlocation = allowed.includes('attendeePhone') ? { type:'attendeePhone', phone:'+1...' } : { type: allowed[0] };","handlingStrategy":"validation","validationCode":"const et = await api.get(`/v2/event-types/${eventTypeId}`);\nconst allowedTypes = et.data.locations.map(l => l.type);\nif (typeof body.location === 'object' && !allowedTypes.includes(body.location.type)) {\n  throw new Error(`location type not allowed; pick one of ${allowedTypes.join(', ')}`);\n}","typeGuard":"const isAllowedLocationType = (type: string, allowed: string[]): boolean => allowed.includes(type);","tryCatchPattern":"try { await api.post('/v2/bookings', body); }\ncatch (e) {\n  if (e.response?.status === 400 && /not valid for event type with id/.test(e.response.data.message)) {\n    /* switch body.location.type to one listed in the error and retry */\n  } else throw e;\n}","preventionTips":["Fetch the event type and send only a location type present in its locations.","Send a string location for backwards compatibility when unsure.","Update the event type's locations if the booker needs a different type."],"tags":["api","bookings","location","event-types","validation","nestjs"],"backgroundTag":null,"analyzedSha":"176037d0afbe572f870a3c702985e7cd83fe6c0c","analyzedAt":"2026-08-12T19:12:41.464Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}