prisma / prisma

Next-generation ORM for Node.js & TypeScript | PostgreSQL, MySQL, MariaDB, SQL Server, SQLite, MongoDB and CockroachDB
https://www.prisma.io
Apache License 2.0
39.65k stars 1.55k forks source link

Error: Maximum call stack size exceeded is thrown after I used clientExtensions as preview feature. #17236

Closed ashish336b closed 1 year ago

ashish336b commented 1 year ago

Bug description

I implemented the clientExtensions feature as a preview, then executed npx prisma generate. After running my code with ts-node, I encountered an error with the maximum call stack size, which I believe is caused by a TypeScript that was triggered by the addition of the clientExtensions preview feature in prisma schema.

How to reproduce

  1. Make sure you have schema.prisma that have definition of implicit many to many relation. Prisma version is 4.7.0
  2. Add clientExtensions as preview feature.
  3. run npx prisma generate
  4. Error occurs saying maximum call stack exceeded.

Expected behavior

No response

Prisma information

// Add your schema.prisma
// Add your code using Prisma Client

Environment & setup

Prisma Version

mcbethio commented 1 year ago

Hey @ashish336b,

Can you send us your prisma schema (it really helps us reproduce quickly). Also, can you try on current version?

millsp commented 1 year ago

Hey @ashish336b, thanks for the report. Would you mind trying this experimental version? @prisma/client 4.9.0-integration-feat-client-ext-generic-type-api.13

ashish336b commented 1 year ago

@millsp will try this experimental version. Thanks.

ashish336b commented 1 year ago

The issue still persists even after using the version suggested by @millsp. It appears to occur in code bases that include relationships. I am still unsure of the cause of the issue.

error TS2551: Property 'project' does not exist on type 'GetResult<{ projectId: number; nhsspId: number; }, unknown>'. Did you mean 'projectId'?
bsplosion commented 1 year ago

I can confirm, had the same thing happen. This was triggered during type checking for TypeScript and looks like this:

RangeError: Maximum call stack size exceeded
    at getTypeId (C:\path\to\project\node_modules\typescript\lib\typescript.js:62407:27)
    at isMarkerType (C:\path\to\project\node_modules\typescript\lib\typescript.js:68463:36)
    at structuredTypeRelatedToWorker (C:\path\to\project\node_modules\typescript\lib\typescript.js:67109:68)
    at structuredTypeRelatedTo (C:\path\to\project\node_modules\typescript\lib\typescript.js:66991:30)
    at recursiveTypeRelatedTo (C:\path\to\project\node_modules\typescript\lib\typescript.js:66956:30)
    at isRelatedTo (C:\path\to\project\node_modules\typescript\lib\typescript.js:66477:25)
    at eachTypeRelatedToType (C:\path\to\project\node_modules\typescript\lib\typescript.js:66793:41)
    at unionOrIntersectionRelatedTo (C:\path\to\project\node_modules\typescript\lib\typescript.js:66668:25)
    at structuredTypeRelatedToWorker (C:\path\to\project\node_modules\typescript\lib\typescript.js:67090:34)
    at structuredTypeRelatedTo (C:\path\to\project\node_modules\typescript\lib\typescript.js:66991:30)

The feature actually wasn't being leveraged in our code yet but was just added as a preview feature to test out with some candidate functionality soon. We changed previewFeatures = ["fullTextSearch", "clientExtensions"] to previewFeatures = ["fullTextSearch"] and TypeScript call stacks stopped having any issues.

Unfortunately I only found this problem by stepping through changes and reverting until we got a clean build since logging was incredibly vague. If it helps, we're building with NextJS 13.1.2, NX 15.5.1, TypeScript 4.9.4. Let me know if there's some better way to get the call stack that triggered the issue.

millsp commented 1 year ago

The call stack issue should be fixed now and is tested with a regression test. I wasn't able to reproduce the missing relation issue, but this has been reported by other users as well. Could you please create a new issue for it and give us a schema as well as your tsconfig. That would be super helpful, thanks!

bsplosion commented 1 year ago

@millsp is there a certain build or PR we should test? I was able to reproduce on Prisma 4.8.1 reliably only two days ago and haven't seen a commit or tag tied to this.

ashish336b commented 1 year ago

If there is any release related to this issue fixes I will try it out on my code base.

millsp commented 1 year ago

We are releasing the fix for tomorrow's 4.9.0 release but you can also try it out immediately if you want via 4.9.0-dev.70.

WARDHAN10 commented 1 year ago

getting same issue can anybody help

// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema

generator client {
  provider        = "prisma-client-js"
}

datasource db {
  provider = "mongodb"
  url      = env("DATABASE_URL")
}

enum Roles {
  user
  admin
  sales
  operation
}

enum UserRole {
  user
  agent
}

enum EntryTypes {
  regular
  express
}

enum AddressTypes {
  rented
  owned
}

enum EmploymentStatus {
  employed
  unEmployed
  student
  retired
  selfEmployed
  other
}

enum OtherIncomeTypes {
  savings
}

enum RelationshipStatus {
  married
  divorced
  single
}

enum PaymentAction {
  visaPayment
}

enum PaymentStatus {
  full
  partial
}

enum Booking {
  hotel
  flight
  none
}

enum InputType {
  checkBox
  radioButton
  singleUplaod
  multiUpload
  datePicker
  slider
  dropDown
  input
  textArea
  richText
}

enum VisaType {
  sticker
  eVisa
}

model Organizations {
  id            String               @id @default(auto()) @map("_id") @db.ObjectId
  name          String
  pricing       OrganizationPricing? //Pricing
  businessEmail String
  logo          String
  heading       String
  subHeading    String?
  domain        String
  users         Users[]
  countries     Countries[]
  overseer      Overseers[]          @relation(fields: [overseers], references: [id])
  overseers     String[]             @db.ObjectId
}

model Users {
  id             String         @id @default(auto()) @map("_id") @db.ObjectId
  email          String?        @unique
  firstName      String?
  lastName       String?
  role           UserRole       @default(user)
  mobile         String         @unique
  refreshToken   String?
  countryCode    String
  createdAt      DateTime       @default(now())
  updatedAt      DateTime       @updatedAt
  organization   Organizations? @relation(fields: [organizationId], references: [id])
  organizationId String?        @db.ObjectId
  Applications   Applications[]
  travellers     Travellers[]
}

model Overseers {
  id            String          @id @default(auto()) @map("_id") @db.ObjectId
  firstName     String?
  lastName      String?
  email         String          @unique
  refreshToken  String?
  password      String          @unique
  mobile        Int?
  roles         Roles[]         @default([admin])
  organizations String[]        @db.ObjectId
  organization  Organizations[] @relation(fields: [organizations], references: [id])
}

model Countries {
  id             String            @id @default(auto()) @map("_id") @db.ObjectId
  name           String?
  code           String?
  visaType       CountryVisaType[]
  flag           String?
  isActive       Boolean?          @default(false)
  countryStep    CountryStep[] //title,order_number,title_image
  countryFaq     CountryFaq[] //question,answer,order_no 
  documents      Document[]
  formFields     FormField[]
  slug           String?
  organizations  Organizations?    @relation(fields: [organizationId], references: [id])
  organizationId String?           @db.ObjectId
  insurance      Insurances?       @relation(fields: [insuranceId], references: [id])
  createdAt      DateTime          @default(now())
  updatedAt      DateTime          @updatedAt
  applications   Applications[]
  insuranceId    String?           @db.ObjectId
}

model Applications {
  id                     String                  @id @default(auto()) @map("_id") @db.ObjectId
  country                Countries               @relation(fields: [countryId], references: [id])
  creator                Users                   @relation(fields: [userId], references: [id])
  status                 String
  visaType               CountryVisaType
  currentStep            String
  tentativeArrivalDate   DateTime
  tentativeDepartureDate DateTime
  remark                 String
  slug                   String
  booking                Booking
  travellerApplication   TravellerApplications[]
  wantInsurance          Boolean
  insuraceDoc            String[]
  appointmentDetail      AppointmentDetail
  submittedAt            DateTime
  paymentStatus          PaymentStatus
  priceBreakUp           PriceBreakUp
  transactions           Transactions[]
  createdAt              DateTime                @default(now())
  updatedAt              DateTime                @updatedAt
  userId                 String                  @db.ObjectId
  countryId              String                  @db.ObjectId
}

model Transactions {
  id                       String        @id @default(auto()) @map("_id") @db.ObjectId
  action                   PaymentAction
  currency                 String
  paymentMode              String
  amount                   Int
  status                   Int
  paymentProcessorMetadata Json
  priceBreakUp             PriceBreakUp
  createdAt                DateTime
  updatedAt                DateTime
  applications             Applications? @relation(fields: [applicationsId], references: [id])
  applicationsId           String        @db.ObjectId
}

model Insurances {
  id        String             @id @default(auto()) @map("_id") @db.ObjectId
  countries Countries[]
  partner   String
  type      String
  createdAt DateTime           @default(now())
  updatedAt DateTime           @updatedAt
  prices    Insurancepricing[]
}

model Travellers {
  id              String    @id @default(auto()) @map("_id") @db.ObjectId
  address         Addresses
  dob             DateTime
  email           String
  firstName       String
  lastName        String
  haveDiseases    Boolean
  isVerified      Boolean
  contactNo       String
  nomineeName     String
  nomineeRelation String
  createdAt       DateTime  @default(now())
  updatedAt       DateTime  @updatedAt
  otherDisease    String
  creator         Users     @relation(fields: [userId], references: [id])
  userId          String    @db.ObjectId
}

model CountryVisaTypes {
  id                  String                @id @default(auto()) @map("_id") @db.ObjectId
  name                String
  visaPrice           CountryVisaPrice[]
  durationInDays      Int
  processingTime      String
  stayDuration        String
  validity            String
  isAgeAffect         Boolean
  entryType           EntryTypes
  createdAt           DateTime              @default(now())
  updatedAt           DateTime              @updatedAt
  tags                String[]
  visaFeeType         String
  VisaType            VisaType
  organizationPricing OrganizationPricing[]
}

model Documents {
  id                 String    @id @default(auto()) @map("_id") @db.ObjectId
  name               String
  displayName        String
  input              InputType
  tags               String[]
  section            String[]
  info               String
  sampleDoc          String[]
  teleportWillUpload Boolean
  show               Boolean
  visaType           VisaType
}

model FormFields {
  id        String      @id @default(auto()) @map("_id") @db.ObjectId
  title     String
  input     InputType
  info      String
  condition Condition[]
  show      Boolean
  visaType  VisaType
}

type CountryStep {
  title       String
  orderNumber String
  titleImage  String
}

type CountryFaq {
  question    String
  answer      String
  orderNumber String
}

type OrganizationPricing {
  organizationId   String
  organizationName String
  teleportFee      Float
  teleportAgentFee Float
}

type CountryVisaType {
  name           String
  visaPrice      CountryVisaPrice[]
  durationInDays Int
  processingTime String
  stayDuration   String
  isAgeAffect    Boolean
  entryType      EntryTypes
  validity       String
  tags           String
  visaFeeType    String
}

type CountryVisaPrice {
  maxAge               Int
  minAge               Int
  appointmentFee       Float
  embassyFee           Float
  ignoreAppointmentFee Boolean
  ignoreEmbassyFee     Boolean
  isDefault            Boolean
  label                String
}

type Insurancepricing {
  minAge      Int
  maxAge      Int
  minDuration Int
  maxDuration Int
  price       Float
}

type PriceBreakUp {
  totalAppointmentFee   Float
  totalEmbassyFee       Float
  totalInsuranceFee     Float
  totalTeleportAgentFee Float
  totalFeleportFee      Float
}

type AppointmentDetail {
  preferredSlot1           String
  preferredSlot2           String
  preferredAppointmentDate String
  appointmentAddress       String
}

type TravellerApplications {
  traveller          Traveller
  visaApplication    ApplicationForm[]
  visaDocument       ApplicationDocument[]
  travellarVisaPrice TravellarVisaPrice
  visaDocumentStatus String[]
  status             String
}

type Addresses {
  city    String
  country String
  line1   String
  line2   String
  pincode String
  state   String
}

type Traveller {
  address         Addresses
  dob             DateTime
  email           String
  firstName       String
  lastName        String
  haveDiseases    Boolean
  isVerified      Boolean
  contactNo       String
  nomineeName     String
  nomineeRelation String
  otherDisease    String
  creatorId       String
}

type TravellarVisaPrice {
  amount              Float
  appointmentEee      Float
  embassyFee          Float
  teleportAgentAmount Float
  teleportFee         Float
}

// add visatype model and type
type Document {
  id                 String
  name               String?
  displayName        String?
  input              InputType?
  tags               String[]
  section            String[]
  info               String?
  sampleDoc          String[]
  teleportWillUpload Boolean?
  show               Boolean?
  visaType           VisaType
}

type FormField {
  id        String
  title     String?
  input     InputType?
  info      String?
  condition Condition[]
  show      Boolean?
  visaType  VisaType
}

type Condition {
  value     String
  operator  String
  formField FormField[]
}

type ApplicationForm {
  formField FormField
  input     Json
}

type ApplicationDocument {
  document Document
  input    Json
}
millsp commented 1 year ago

@WARDHAN10 Your schema is not using the clientExtensions preview feature. In any case, please open a new issue. Thanks!