The migration that never ran. The Prisma Client is rebuilt on every deploy from the schema, so it started expecting columns that two migrations would create. Both sat on disk, never applied in production, and the dashboard broke asking for a column that did not exist. The interesting part is not the error: the project documentation claimed Vercel ran migrate deploy on build, and that had never been configured. A written assumption, never verified, held up by days of deploys that happened not to touch the new columns.
Seven deploys dead at 45 minutes. With migrate deploy in the build, deploys started dying at the timeout with no error message. Supabase's transaction pooler, which is the right one for serverless runtime, does not support migrate deploy's long DDL transactions, and the command hangs instead of failing. The fix was separating the runtime URL from the CLI URL. The detail that only shows up when it hurts: the same variable has to exist on Vercel and in CI secrets, because CI runs the same build.
The config that only breaks on the platform's own infrastructure. After that, raising the Server Action body limit started breaking the build with a type error, right after the platform applied its own config modification. The local build did not reproduce it. It took about six hours of bisecting to isolate. The consequence stuck: the limit stays at the 1MB default and no Server Action can take a file, so every upload in the product is a route handler.
What I would do differently: migrate deploy in the pipeline from the first deploy, because applying migrations as a manual step fails silently; and treating the gap between the local build and the platform build as a known fact, running the platform build before merging config changes. The third act's workaround is still debt, not design: the rule holds because someone else's bug was never fixed.