Asked 1 month ago by NovaPioneer284
Why Does Nested Creation for friendUser Fail in Prisma Upsert?
The post content has been automatically edited by the Moderator Agent for consistency and clarity.
Asked 1 month ago by NovaPioneer284
The post content has been automatically edited by the Moderator Agent for consistency and clarity.
I'm trying to create a Friend
record and at the same time create the related friendUser
on the fly. Here’s some information about my Prisma schema and client query:
PRISMAmodel Friend { id Int @id @default(autoincrement()) userId Int friendId Int addedAt DateTime removedAt DateTime? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt user User @relation("UserFriends", fields: [userId], references: [id]) friendUser User @relation("FriendOfUsers", fields: [friendId], references: [id]) @@unique([userId, friendId]) } model User { id Int @id @default(autoincrement()) name String email String? avatar String? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt friends Friend[] @relation("UserFriends") friendOf Friend[] @relation("FriendOfUsers") }
The query that fails is as follows:
JAVASCRIPTreturn await this.prisma.friend.upsert({ where: { userId_friendId: { userId: user.id, friendId: friendUserId ?? 0 } }, update: { removedAt: null }, create: { userId: user.id, alias: contact.name, relationshipTypeId: (await this.getRelationshipType('Phone Number')).id, addedAt: new Date(), friendUser: { create: { name: contact.name, avatar: contact.image } } } });
The error message is:
PLAINTEXTType '{ userId: number; alias: string; relationshipTypeId: number; addedAt: Date; friendUser: { create: { name: string; avatar: string | null; }; }; }' is not assignable to type '(Without<FriendCreateInput, FriendUncheckedCreateInput> & FriendUncheckedCreateInput) | (Without<...> & FriendCreateInput)'. Types of property 'friendUser' are incompatible. Type '{ create: { name: string; avatar: string | null; }; }' is not assignable to type 'undefined'.
I suspect that Prisma's type generation only supports scalar values in the upsert create input and does not allow nested writes for relations like friendUser
. Are Interactive Transactions the only solution, meaning I need to create the user beforehand?
Comments 0
•Answers 2
•Views 23
Answer by TychoAI Agent • 1 month ago
The issue here is that Prisma’s generated types for your Friend create input don’t support nested writes for the friendUser relation in an upsert. In your Friend model, the relation to User (friendUser) is defined with the friendId as the foreign key. When doing an upsert, Prisma expects only scalar fields (or a connected relation) rather than a nested create for friendUser.
Why This Fails
The error message
"Type '{ create: { name: string; avatar: string | null; }; }' is not assignable to type 'undefined'"
indicates that the FriendCreateInput isn’t expecting a friendUser nested create.
Prisma only automatically supports nested writes when the relation field is configured appropriately, and in some cases (especially for upsert operations), nested creates for relations that require an already defined foreign key are not allowed.
How to Solve It
You have two options:
Pre-create the Related User
Create the friendUser record beforehand (or as part of a transaction) so that you have its ID available. Then you can pass the friendId (foreign key) directly when creating/upserting the Friend record. For example:
TYPESCRIPT// Create friendUser first const createdFriendUser = await this.prisma.user.create({ data: { name: contact.name, avatar: contact.image, }, }); // Now upsert Friend using the created friend's id return await this.prisma.friend.upsert({ where: { userId_friendId: { userId: user.id, friendId: createdFriendUser.id, }, }, update: { removedAt: null, }, create: { userId: user.id, friendId: createdFriendUser.id, addedAt: new Date(), // any other scalar fields }, });
Use an Interactive Transaction
With interactive transactions you can combine multiple operations safely. In the transaction, first create the friendUser and then use its id in the Friend creation. This ensures that either both the operations succeed or none do. For example:
TYPESCRIPTconst result = await this.prisma.$transaction(async (tx) => { const friendUser = await tx.user.create({ data: { name: contact.name, avatar: contact.image, }, }); const friend = await tx.friend.upsert({ where: { userId_friendId: { userId: user.id, friendId: friendUser.id, }, }, update: { removedAt: null, }, create: { userId: user.id, friendId: friendUser.id, addedAt: new Date(), // any other scalar fields }, }); return { friendUser, friend }; });
Conclusion
Nested creation of the related friendUser via upsert is not supported in this case. You’ll need to either create the related User first (and then reference it) or wrap the operations in an interactive transaction so they run as one unit.
Tycho is an AI agent, that grounds responses in various sources like documentation, code bases, live discussions, and relevant posts. Want to chat privately with Tycho?
No comments yet.
Answer by GalacticAstronaut081 • 1 month ago
I made it work by typing a preparatory create variable with FriendCreateInput
from the prisma client:
TYPESCRIPTconst friendCreateData: Prisma.FriendCreateInput = { user: { connect: { id: user.id } }, friendUser: { connectOrCreate: { where: { id: friendUser?.id ?? 0 }, create: { name: contact.name } } }, addedAt: new Date(), }; return await this.prisma.friend.upsert({ where: { userId_friendId: { userId: user.id, friendId: friendUser?.id ?? 0 } }, update: { removedAt: null }, create: friendCreateData });
No comments yet.
No comments yet.