Prisma ORMRunbook 0/4 done
P2025

Prisma ORM Error P2025: Record not found

Error✕ Not retryable · fix the payloadHTTP 404 Not FoundDatabase
TL;DR · 10-second read

update, delete, findUniqueOrThrow or a nested connect targeted a row that does not exist. Map P2025 to 404, or use updateMany/deleteMany when a missing row is acceptable.

Identify: does your log match?

What you see · exact log / response
PrismaClientKnownRequestError:
Invalid `prisma.post.update()` invocation in
/app/src/routes/posts.ts:41:28

An operation failed because it depends on one or more records that were required but not found. No record was found for an update.
  code: 'P2025',
  meta: { modelName: 'Post', cause: 'Record to update not found.' }
  1. High

    Stale or wrong id from client

    The row was deleted by another request, or the id belongs to another tenant filtered out by where.

  2. Medium

    Extra filters in a unique where

    where: { id, authorId } on update requires both to match. A non-owner request finds no row and throws P2025.

  3. Low

    Nested connect to missing relation

    connect: { id } on a relation whose target row does not exist also raises P2025.

Fix

Return 404 instead of a 500

✕ Broken · TypeScript
const post = await prisma.post.delete({ where: { id } });
return Response.json(post);
✓ Fixed · TypeScript
import { Prisma } from '@prisma/client';

try {
  const post = await prisma.post.delete({ where: { id } });
  return Response.json(post);
} catch (e) {
  if (e instanceof Prisma.PrismaClientKnownRequestError && e.code === 'P2025') {
    return Response.json({ error: 'Not found' }, { status: 404 });
  }
  throw e;
}

A missing row is a client-facing condition, not a server crash.

Verify: reproduce it on purpose

Reproduce locally · node
$ node -e "const {PrismaClient}=require('@prisma/client');new PrismaClient().user.delete({where:{id:-1}}).catch(e=>console.log(e.code, e.meta))"

Run it against a dev environment to trigger P2025 on purpose and test your error handler.

Prevent

  • Use findUnique + null check for reads, not findUniqueOrThrow, when 404 is expected.
  • Scope where clauses by tenant and treat P2025 as 404.
  • Make delete endpoints idempotent with deleteMany.

FAQ

Why did rejectOnNotFound stop working?

It was removed in Prisma 5. Use findUniqueOrThrow / findFirstOrThrow, which throw P2025.

Is P2025 thrown inside $transaction?

Yes, and it rolls back the whole transaction. Check existence first if partial success is acceptable.

How do I tell which relation was missing?

Read e.meta.cause and e.meta.modelName; nested writes include the relation name in the message.

Related errors

Last verified 2026-10-15 · Source: Prisma error reference P1000–P6010 · Official docs ↗ · ~6,600 searches/mo