{"record":{"id":"ad4c5aa579db08a6","repo":"calcom/cal.diy","slug":"error-message-ad4c5a","errorCode":null,"errorMessage":"${error.message}","messagePattern":"\\$\\{error\\.message\\}","errorType":"http","errorClass":"BadRequestException","httpStatus":400,"severity":"error","filePath":"apps/api/v2/src/platform/event-types-private-links/services/private-links.service.ts","lineNumber":44,"sourceCode":"      const transformedInput = this.inputService.transformCreateInput(input);\n      const created = await this.repo.create(eventTypeId, {\n        link: generateHashedLink(userId),\n        expiresAt: transformedInput.expiresAt ?? null,\n        maxUsageCount: transformedInput.maxUsageCount ?? null,\n      });\n      const mapped: PrivateLinkData = {\n        id: created.link,\n        eventTypeId,\n        isExpired: isLinkExpired(created as any),\n        bookingUrl: `${process.env.NEXT_PUBLIC_WEBAPP_URL || \"https://cal.com\"}/d/${created.link}`,\n        expiresAt: created.expiresAt ?? null,\n        maxUsageCount: (created as any).maxUsageCount ?? null,\n        usageCount: (created as any).usageCount ?? 0,\n      };\n      return this.outputService.transformToOutput(mapped);\n    } catch (error) {\n      if (error instanceof Error) {\n        throw new BadRequestException(error.message);\n      }\n      throw new BadRequestException(\"Failed to create private link\");\n    }\n  }\n\n  async getPrivateLinks(eventTypeId: number): Promise<PrivateLinkOutput[]> {\n    try {\n      const links = await this.repo.listByEventTypeId(eventTypeId);\n      const mapped: PrivateLinkData[] = links.map((l) => ({\n        id: l.link,\n        eventTypeId,\n        isExpired: isLinkExpired(l as any),\n        bookingUrl: `${process.env.NEXT_PUBLIC_WEBAPP_URL || \"https://cal.com\"}/d/${l.link}`,\n        expiresAt: l.expiresAt ?? null,\n        maxUsageCount: l.maxUsageCount ?? null,\n        usageCount: l.usageCount ?? 0,\n      }));\n      return this.outputService.transformArrayToOutput(mapped);","sourceCodeStart":26,"sourceCodeEnd":62,"githubUrl":"https://github.com/calcom/cal.diy/blob/176037d0afbe572f870a3c702985e7cd83fe6c0c/apps/api/v2/src/platform/event-types-private-links/services/private-links.service.ts#L26-L62","documentation":"In PrivateLinksService.createPrivateLink's catch block: if the underlying failure (transformCreateInput validation, generateHashedLink, repo.create, or the mapping step) is an instance of Error, its .message is re-thrown inside a BadRequestException. So the literal text is whatever the inner code raised: most commonly 'Either expiresAt or maxUsageCount must be provided' or 'Provide only one of expiresAt or maxUsageCount' from the input service, but it could also be a Prisma/DB error message.","triggerScenarios":"Calling POST /v2/event-types/{id}/private-links with input that fails transformCreateInput (errors 392/393); a DB constraint failure during repo.create (e.g. unique violation on the generated link); generateHashedLink throwing because userId is invalid; an unexpected Prisma error whose message leaks through.","commonSituations":"Invalid input payload; collision on the hashed link (rare); DB connection issue mid-insert; an unhandled Prisma validation error whose message is forwarded raw.","solutions":["Read the forwarded message; for input errors, fix the payload per errors 392/393.","For DB-shaped messages, inspect server logs for the original Prisma error and address the constraint.","Validate the input client-side before posting (see defense strategies) to avoid the round-trip."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"try {\n  inputService.transformCreateInput(input);\n} catch (e) {\n  // surface e.message to the user (e.g. 'Either expiresAt or maxUsageCount must be provided')\n}","typeGuard":null,"tryCatchPattern":"try {\n  await privateLinksService.createPrivateLink(eventTypeId, userId, input);\n} catch (e) {\n  if (e instanceof BadRequestException) {\n    // e.message is the inner Error.message; handle known input-validation strings\n  } else throw e;\n}","preventionTips":["Validate the input client-side before POST.","Read the forwarded message to distinguish input errors from DB errors.","Wrap createPrivateLink callers in try/catch and map known messages to user-facing hints."],"tags":["private-links","catch-all","api-v2"],"backgroundTag":null,"analyzedSha":"176037d0afbe572f870a3c702985e7cd83fe6c0c","analyzedAt":"2026-08-12T19:12:41.464Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}