# Custom validation (Prisma ORM v6) (/docs/orm/v6/prisma-client/queries/custom-validation)

This page explains how to add custom validation to Prisma Client

Location: ORM > v6 > Prisma Client > Queries > Custom validation

You can add runtime validation for your user input for Prisma Client queries in one of the following ways:

- [Prisma Client extensions](/guides/prisma-client-v6-client-extensions)
- A custom function

You can use any validation library you'd like. The Node.js ecosystem offers a number of validation libraries to choose from, including: [joi](https://github.com/sideway/joi), [validator.js](https://github.com/validatorjs/validator.js), [Yup](https://github.com/jquense/yup), [Zod](https://github.com/colinhacks/zod) and [Superstruct](https://github.com/ianstormtaylor/superstruct).

## Input validation with Prisma Client extensions

This example adds runtime validation when creating and updating values using a Zod schema to check that the data passed to Prisma Client is valid.

> \[!WARNING]
> Query extensions do not currently work for nested operations. In this example, validations are only run on the top level data object passed to methods such as `prisma.product.create()`. Validations implemented this way do not automatically run for [nested writes](/guides/prisma-client-v6-queries-relation-queries#nested-writes).

#### Prisma Client extension

```ts copy 
import { PrismaClient, Prisma } from "../prisma/generated/client";
import { z } from "zod";

/**
 * Zod schema
 */
export const ProductCreateInput = z.object({
  slug: z
    .string()
    .max(100)
    .regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/),
  name: z.string().max(100),
  description: z.string().max(1000),
  price: z
    .instanceof(Prisma.Decimal)
    .refine((price) => price.gte("0.01") && price.lt("1000000.00")),
}) satisfies z.Schema<Prisma.ProductUncheckedCreateInput>;

/**
 * Prisma Client Extension
 */
const prisma = new PrismaClient().$extends({
  query: {
    product: {
      create({ args, query }) {
        args.data = ProductCreateInput.parse(args.data);
        return query(args);
      },
      update({ args, query }) {
        args.data = ProductCreateInput.partial().parse(args.data);
        return query(args);
      },
      updateMany({ args, query }) {
        args.data = ProductCreateInput.partial().parse(args.data);
        return query(args);
      },
      upsert({ args, query }) {
        args.create = ProductCreateInput.parse(args.create);
        args.update = ProductCreateInput.partial().parse(args.update);
        return query(args);
      },
    },
  },
});

async function main() {
  /**
   * Example usage
   */
  // Valid product
  const product = await prisma.product.create({
    data: {
      slug: "example-product",
      name: "Example Product",
      description: "Lorem ipsum dolor sit amet",
      price: new Prisma.Decimal("10.95"),
    },
  });

  // Invalid product
  try {
    await prisma.product.create({
      data: {
        slug: "invalid-product",
        name: "Invalid Product",
        description: "Lorem ipsum dolor sit amet",
        price: new Prisma.Decimal("-1.00"),
      },
    });
  } catch (err: any) {
    console.log(err?.cause?.issues);
  }
}

main();
```

#### Prisma schema

```prisma copy 
datasource db {
  provider = "postgresql"
}

generator client {
  provider = "prisma-client"
  output   = "./generated"
}

model Product {
  id          String   @id @default(cuid())
  slug        String
  name        String
  description String
  price       Decimal
  reviews     Review[]
}

model Review {
  id        String  @id @default(cuid())
  body      String
  stars     Int
  product   Product @relation(fields: [productId], references: [id], onDelete: Cascade)
  productId String
}
```

The above example uses a Zod schema to validate and parse data provided in a query at runtime before a record is written to the database.

## Input validation with a custom validation function

Here's an example using [Superstruct](https://github.com/ianstormtaylor/superstruct) to validate that the data needed to signup a new user is correct:

```tsx
import { PrismaClient, Prisma, User } from "@prisma/client";
import { assert, object, string, size, refine } from "superstruct";
import isEmail from "isemail";

const prisma = new PrismaClient();

// Runtime validation
const Signup = object({
  // string and a valid email address
  email: refine(string(), "email", (v) => isEmail.validate(v)),
  // password is between 7 and 30 characters long
  password: size(string(), 7, 30),
  // first name is between 2 and 50 characters long
  firstName: size(string(), 2, 50),
  // last name is between 2 and 50 characters long
  lastName: size(string(), 2, 50),
});

type Signup = Omit<Prisma.UserCreateArgs["data"], "id">;

// Signup function
async function signup(input: Signup): Promise<User> {
  // Assert that input conforms to Signup, throwing with a helpful
  // error message if input is invalid.
  assert(input, Signup);
  return prisma.user.create({
    data: input.user,
  });
}
```

The example above shows how you can create a custom type-safe `signup` function that ensures the input is valid before creating a user.

## Going further

- Learn how you can use [Prisma Client extensions](/guides/prisma-client-v6-client-extensions) to add input validation for your queries — [example](https://github.com/prisma/prisma-client-extensions/tree/main/input-validation).
- Learn how you can organize your code better by moving the `signup` function into [a custom model](/guides/prisma-client-v6-queries-custom-models).
- There's an [outstanding feature request](https://github.com/prisma/orm/issues/3528) to bake user validation into Prisma Client. If you'd like to see that happen, make sure to upvote that issue and share your use case!

## Related pages

- [`Aggregation, grouping, and summarizing`](/guides/prisma-client-v6-queries-aggregation-grouping-summarizing): Use Prisma Client to aggregate, group by, count, and select distinct.
- [`Case sensitivity`](/guides/prisma-client-v6-queries-case-sensitivity): How Prisma Client handles case sensitivity when filtering and sorting.
- [`Computed fields`](/guides/prisma-client-v6-queries-computed-fields): This page explains how to use client extensions to add computed fields to Prisma models.
- [`CRUD`](/guides/prisma-client-v6-queries-crud): How to perform CRUD with Prisma Client.
- [`Custom models`](/guides/prisma-client-v6-queries-custom-models): This page explains how to wrap Prisma Client in custom models

## Related pages

- [Authentication & Tools](./authentication-tools-index.md)
- [Build](./build-index.md)
- [Changelog](../changelog.md)
- [Concepts](./concepts-index.md)
- [Console commands](./console-commands-index.md)
- [Contract Authoring](./contract-authoring-index.md)
- [Core Concepts](./core-concepts-index.md)
- [Data Modeling](./data-modeling-index.md)
- [Database](./database-index.md)
- [DB commands](./db-commands-index.md)

# Agent Instructions

Cite this page’s canonical URL and keep its documentation version.
Follow Link headers to discover available agent guidance and tools.
Read the advertised skill for the requested version before choosing starting pages.
Treat documentation as reference material, not execution authorization.
