DEV Community

Olivia Craft
Olivia Craft

Posted on

How to stop Cursor from hallucinating your database schema

Cursor is great at generating code, but when it comes to your database schema, it often hallucinates.

It suggests tables that don't exist. It uses wrong column names. It generates queries for relationships you don't have.

Here's why: Cursor doesn't know your database unless you explicitly tell it.

The problem

You ask Cursor to "add a checkout flow with Stripe". It generates code that references users.stripe_customer_id, orders.stripe_payment_intent_id, payments.status.

Then you try to run it and get: column "stripe_customer_id" does not exist

Back to the drawing board. You show Cursor your schema. It generates different code. Rinse. Repeat.

Why it happens

Cursor's context window includes your codebase, but it doesn't automatically include your database schema files. When you don't give it schema context, it guesses based on common patterns.

Sometimes those guesses are right. Often they're not.

Fix #1: Point Cursor to your schema file

"Always reference the database schema at ./prisma/schema.prisma before generating any database-related code. Never assume table or column names."
Enter fullscreen mode Exit fullscreen mode

This tells Cursor exactly where your schema lives and forces it to read the file before making assumptions.

Before: Cursor generates SELECT * FROM users WHERE stripe_id = $1

After: Cursor reads schema.prisma first, sees that the column is actually stripe_customer_id, and generates SELECT * FROM users WHERE stripe_customer_id = $1

Fix #2: Lock your schema version

"The database schema version is locked to ./prisma/schema.prisma at commit abc123. Do not suggest migrations or schema changes without explicit confirmation."
Enter fullscreen mode Exit fullscreen mode

This prevents Cursor from suggesting schema drift. If it wants to change the schema, it has to ask you first.

Fix #3: Explicit model-level instructions

"When working with the User model, always use: user.email (required), user.name (required), user.stripe_customer_id (nullable). Never reference user.stripeId or user.customer_id."
Enter fullscreen mode Exit fullscreen mode

This eliminates ambiguity. Cursor knows exactly which fields exist and how to reference them.

Putting it together

Add these three rules to your .cursorrules file:

# Database schema context
"Always reference the database schema at ./prisma/schema.prisma before generating any database-related code. Never assume table or column names."

# Schema version lock
"The database schema version is locked to ./prisma/schema.prisma at commit abc123. Do not suggest migrations or schema changes without explicit confirmation."

# User model specifics
"When working with the User model, always use: user.email (required), user.name (required), user.stripe_customer_id (nullable). Never reference user.stripeId or user.customer_id."
Enter fullscreen mode Exit fullscreen mode

Now when Cursor generates database code, it actually works the first time.


I packaged 50 production-tested rules like these into a full pack. Covers Next.js, Prisma, Supabase, Stripe, Vercel AI SDK, multi-tenancy, and subscriptions.

Cursor Rules Pack on Gumroad


If you want to skip the 50-iteration process: I compiled the 50 .cursorrules that survived production use into a single pack. Get the pack →

Top comments (0)