How to skip undefined unique values in connect fields in Prisma Client

|3 min read

Connecting nested records can be tricky, especially when working with undefined values.

This article covers the problem you might face working with undefined unique nested records, why that’s the case, and how to get around it.

The challenge of working with undefined nested values

Assuming you have the following schema:

model Post {
  id          Int      @id @default(autoincrement())
  createdAt   DateTime @default(now())
  updatedAt   DateTime @updatedAt
  title       String
  content     String?
  isPublished Boolean  @default(false)

  authorId Int?
  author   User? @relation(fields: [authorId], references: [id])
}

model User {
  id    Int     @id @default(autoincrement())
  email String  @unique
  name  String?

  posts Post[]
}

… and you’re creating a post record and want to connect an author, you can connect the author relation directly using the foreign key as follows:

const authorId = undefined;

const newPost = await prisma.post.create({
  data: {
    title: "New Post with undefined authorId",
    authorId,
  },
});

When the value is set undefined, it is equivalent to not having the field. The payload for the query would be equal to the following:

data: {
  title: "New Post with undefined authorId";
}

Another way you can connect nested records is using a relation query as follows:

const authorId = undefined;

const newPost = await prisma.post.create({
  data: {
    title: "New Post with undefined authorId",
    author: {
      connect: { id: authorId },
    },
  },
});

However, in the above query, since the authorId value is undefined, the query’s payload would resemble this:

data: {
  title: "New Post with undefined authorId";
  author: {
    connect: {
    }
  }
}

The above payload is invalid since the query expects a value in the connect property.

On attempting to run the query, it will fail with the following error (Expand to view the error)
PrismaClientValidationError:
Invalid `prisma.post.create()` invocation in
/project_path/index.ts:8:37

  5 async function main() {
  6   const authorId = undefined
  7
8   const newPost = await prisma.post.create({
        data: {
          title: 'New Post with undefined authorId',
          author: {
          ~~~~~~
            connect: {
              id: authorId
            }
          }
        },
        include: {
          author: true
        }
      })

Unknown arg `author` in data.author for type PostUncheckedCreateInput. Did you mean `authorId`? Available args:
type PostUncheckedCreateInput {
  id?: Int
  createdAt?: DateTime
  updatedAt?: DateTime
  title: String
  content?: String | Null
  isPublished?: Boolean
  authorId?: Int | Null
}


    at Yn.validate (/project_path/node_modules/@prisma/client/src/runtime/query.ts:249:19)
    at Ur.createMessage (//project_path/node_modules/@prisma/client/src/runtime/core/protocol/graphql.ts:81:14)
    at cb (/Users/ruheni/project_path/node_modules/@prisma/client/src/runtime/getPrismaClient.ts:1078:27)
    at runInChildSpan (/project_path/node_modules/@prisma/engine-core/src/tracing/runInChildSpan.ts:20:41)
    at t._executeRequest (/project_path/node_modules/@prisma/client/src/runtime/getPrismaClient.ts:1077:31)
    at async t._request (/project_path/node_modules/@prisma/client/src/runtime/getPrismaClient.ts:1036:14) {
  clientVersion: '4.10.1'
}

Workaround for unique undefined relation query

One workaround is by checking the value of the unique property using the && logical operator — authorId in this case:

const authorId = undefined;

const newPost = await prisma.post.create({
  data: {
    title: "New Post with undefined authorId",
    author: authorId && { connect: { id: authorId } },
  },
});

The payload from the query would be as follows, which is valid:

data: {
  title: "New Post with undefined authorId";
  author: {
  }
}

Here’s another possible workaround, with some type-safety, for skipping unique fields:

const authorId = undefined;

const connectAuthorId =
  typeof authorId !== "undefined"
    ? {
        connect: {
          id: authorId,
        } satisfies Prisma.UserCreateNestedOneWithoutPostsInput["connect"],
      }
    : {};

const newPost = await prisma.post.create({
  data: {
    title: "3rd Post with undefined authorId",
    author: connectAuthorId,
  },
});