{"record":{"id":"3198f7ac66516dda","repo":"calcom/cal.diy","slug":"booking-location-with-type-location-as-bookingi","errorCode":null,"errorMessage":"Booking location with type ${(location as BookingInputLocation_2024_08_13).type} not valid.","messagePattern":"Booking location with type (.+?) not valid\\.","errorType":"exception","errorClass":"BadRequestException","httpStatus":400,"severity":"error","filePath":"apps/api/v2/src/platform/bookings/2024-08-13/services/input.service.ts","lineNumber":372,"sourceCode":"        optionValue: \"\",\n      };\n    }\n\n    if (location.type === \"attendeePhone\") {\n      return {\n        value: \"phone\",\n        optionValue: location.phone,\n      };\n    }\n\n    if (location.type === \"attendeeDefined\") {\n      return {\n        value: \"somewhereElse\",\n        optionValue: location.location,\n      };\n    }\n\n    throw new BadRequestException(\n      `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) {","sourceCodeStart":354,"sourceCodeEnd":390,"githubUrl":"https://github.com/calcom/cal.diy/blob/176037d0afbe572f870a3c702985e7cd83fe6c0c/apps/api/v2/src/platform/bookings/2024-08-13/services/input.service.ts#L354-L390","documentation":"Thrown at the bottom of transformLocation when the location object's type does not match any handled branch (address, link, integration, phone, attendeeAddress, attendeePhone, attendeeDefined, organizersDefaultApp, attendeeDefined). BadRequestException (HTTP 400). It is the defensive fallthrough after the type union check.","triggerScenarios":"POST /v2/bookings with body.location = { type: <unknown value>, ... } where type is not one of the eight supported inputLocations. Normally the BookingInputLocationValidator_2024_08_13 class-validator rejects unknown types first with a different message; this fires only if validation was bypassed or a new type was introduced in the union without a transformLocation branch.","commonSituations":"Typos in the type field ('adress', 'integrations'); using internal type names ('inPerson', 'somewhereElse') instead of API type names ('address', 'attendeeDefined'); version skew where a newer client sends a type the deployed server does not know; bypassing the DTO validation layer.","solutions":["Use one of the documented inputLocations values: address, link, integration, phone, attendeePhone, attendeeAddress, attendeeDefined, organizersDefaultApp.","Verify the type matches the API version deployed on the server.","Do not send internal Cal type names (inPerson, userPhone, somewhereElse) — those are output-only.","Run the BookingInputLocationValidator on the payload before sending to catch typos early."],"exampleFix":"// before\nlocation: { type: 'inPerson', address: '123 St' }  // internal name\n\n// after\nlocation: { type: 'address' }","handlingStrategy":"type-guard","validationCode":"import { inputLocations } from '@calcom/platform-types/bookings/2024-08-13/inputs/location.input';\nif (typeof body.location === 'object' && !inputLocations.includes(body.location.type)) {\n  throw new Error(`location.type must be one of ${inputLocations.join(', ')}`);\n}","typeGuard":"import { inputLocations } from '@calcom/platform-types/bookings/2024-08-13/inputs/location.input';\nconst isValidLocationType = (t: string): t is typeof inputLocations[number] =>\n  (inputLocations as readonly string[]).includes(t);","tryCatchPattern":"try { await api.post('/v2/bookings', body); }\ncatch (e) {\n  if (e.response?.status === 400 && /location with type.*not valid/i.test(e.response.data.message)) {\n    /* fix the type to one of inputLocations and retry */\n  } else throw e;\n}","preventionTips":["Use only the documented inputLocations type values.","Do not send internal output names (inPerson, userPhone, somewhereElse).","Run BookingInputLocationValidator on the payload client-side."],"tags":["api","bookings","location","validation","nestjs"],"backgroundTag":null,"analyzedSha":"176037d0afbe572f870a3c702985e7cd83fe6c0c","analyzedAt":"2026-08-12T19:12:41.464Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}