You add a field to schema.prisma, use it, and TypeScript refuses:
Object literal may only specify known properties,
and 'archivedAt' does not exist in type 'ProjectSelect'.
Or the mirror image, at runtime, in a deploy that built without complaint:
PrismaClientValidationError:
Unknown argument `archivedAt`. Available options are marked with ?.
Or the strangest version: the code compiles, the query runs, and the column simply is not in the result object.
None of these are bugs in your code. They are all the same thing: the generated client no longer matches the schema.
Why there is a generated client at all
The typed prisma.project.findMany with your exact models, your exact fields
and the ProjectSelect type the error is complaining about is not in any npm
package. prisma generate writes it from schema.prisma. Since Prisma 7 the
prisma-client generator writes plain TypeScript to the output folder the
generator block names, in this repo src/generated/prisma, and you import it
from there:
import type { Project } from "@/generated/prisma/client";
@prisma/client is still a dependency, but only as the runtime that generated
code imports. It exports no models.
That has one consequence worth internalising: the client is build output, not
a dependency. It is derived from schema.prisma the way a compiled bundle is
derived from source. If the source changes and the build does not re-run, you
are looking at stale output. This repo git-ignores the folder, so a fresh
checkout has no client at all until generate runs.
The fix, locally
bun run db:generate
Then restart the TypeScript server. This is the step people miss: the editor's
language server holds the old types in memory and will keep showing the error
after the files on disk are correct. Restart next dev too, since its module
cache has the old client loaded.
bun run db:migrate runs generate before it migrates, which is why this
rarely bites during a normal migration workflow. (Prisma 7's migrate dev no
longer generates on its own; the script does it.) It bites when you edit the
schema and don't migrate: a @@map, an @@index, a comment, a formatting
pass, a change you made intending to migrate later.
The four situations that produce drift
1. Edited the schema, ran nothing. The common one. Generate.
2. Pulled someone else's schema change. Their migration is in your working
tree, your generated client is not. This repo has a postinstall that runs
generate, but whether bun install fires it depends on your package manager
and on whether anything actually changed. After any pull that touches
prisma/, run generate.
3. A deploy restored a cached install. Vercel caches dependencies between
builds. If the cache is a hit, the install can be a no-op and postinstall may
not run, so the build finds no src/generated/prisma at all
(Module not found: Can't resolve '@/generated/prisma/client') or, on a host
that keeps the working directory, a client generated from an older schema. This
is why the build command must be explicit even though postinstall exists:
bun run db:generate && bun run db:migrate:deploy && bun run build
4. Code still imports @prisma/client. Anything written for Prisma 6 (a
snippet, an older library, a copied helper) imports models from
@prisma/client. Under Prisma 7 that package has no generated models, so the
import fails to typecheck, and at runtime it cannot find
.prisma/client/default, even right after a generate. Import from
@/generated/prisma/client instead.
Client drift vs database drift
Two different problems with similar names, worth separating:
- Client drift. Generated code is older than
schema.prisma. Symptom: TypeScript errors, orUnknown argumentat runtime. Fix:prisma generate. - Database drift. The database is not what the migration history says it
should be, usually because someone ran
db pushor changed a table by hand. Symptom:prisma migrate statusreports drift, or a query fails withcolumn ... does not existeven though the client knows about it. Fix: reconcile with a new migration; reset only on a local database.
The tell is which side is stale. If TypeScript knows about the field and Postgres does not, that is database drift. If Postgres knows and TypeScript does not, that is client drift.
Making it not happen again
Generate on install. Already wired: postinstall runs prisma generate,
so every clone, every dependency change and every fresh CI-free environment
gets a correct client without anyone remembering.
Generate in the build command, as above. postinstall does not always fire
on a cache hit, so belt and braces.
Do not commit the generated client. It is build output; committing it
guarantees stale diffs and merge conflicts. This repo lists
/src/generated/prisma/ in .gitignore, and Biome skips it for the same
reason.
Treat a schema edit as a two-command action. Edit, then migrate (or
generate). A schema edit alone is an unfinished change, in the same way that
editing a .proto without regenerating is.
The one-minute triage
When the types look wrong, in order:
bunx prisma validate # is the schema even valid?
bun run db:generate # regenerate; read the output path it prints
bunx prisma migrate status # is the database behind the history?
Then restart the TS server and the dev server. If the error survives all
four, look at the import: a file importing from @prisma/client, or from a
generated folder other than the one schema.prisma names, is reading types
nothing regenerates.