Fix: Prisma Enum Not Working — Invalid Enum Value or Enum Not Recognized
Quick Answer
How to fix Prisma enum errors — schema definition, database sync, TypeScript enum type mismatch, filtering by enum, and migrating existing enum values.
The Problem
Prisma throws an error when using an enum value:
const user = await prisma.user.create({
data: {
email: '[email protected]',
role: 'ADMIN', // Error: Argument role: Invalid value provided. Expected Role, provided String.
},
});Or TypeScript complains about the enum type:
import { Role } from '@prisma/client';
const role: Role = 'ADMIN'; // Error: Type '"ADMIN"' is not assignable to type 'Role'Or an enum query returns no results despite matching data:
const admins = await prisma.user.findMany({
where: { role: 'ADMIN' }, // Returns empty array — enum filtering broken
});Or after changing the enum in schema.prisma, the database still uses the old values.
Why This Happens
Prisma generates TypeScript types from your schema.prisma file. Enum values are generated as a TypeScript enum object, not plain strings. Several things break this:
- Using string literals instead of the generated enum —
role: 'ADMIN'is a string. Prisma expectsrole: Role.ADMIN(the generated enum object) or the client-generated string type. - Out-of-sync generated client — after changing enum values in
schema.prisma, you must runprisma generateto regenerate the TypeScript types. Until then, the old types are in effect. - Migration not run — if you added a new enum value,
prisma db pushorprisma migrate devmust be run to add the value to the database. TypeScript might compile fine, but the database insert will fail. - Database-level enum vs Prisma-level — PostgreSQL and MySQL enforce enum values at the database level. Inserting an invalid string causes a database error, not just a TypeScript error.
- Case sensitivity — Prisma enums are case-sensitive.
ADMIN≠admin≠Admin.
Fix 1: Use the Generated Prisma Enum Object
Import and use the generated enum from @prisma/client:
// schema.prisma
enum Role {
USER
ADMIN
MODERATOR
}
model User {
id String @id @default(cuid())
email String @unique
role Role @default(USER)
}// WRONG — string literal instead of enum
const user = await prisma.user.create({
data: {
email: '[email protected]',
role: 'ADMIN', // TypeScript error + runtime error
},
});
// CORRECT — use the generated Prisma enum
import { PrismaClient, Role } from '@prisma/client';
const prisma = new PrismaClient();
const user = await prisma.user.create({
data: {
email: '[email protected]',
role: Role.ADMIN, // Correct: uses the generated enum
},
});Filtering by enum:
// Using enum value in where clause
const admins = await prisma.user.findMany({
where: { role: Role.ADMIN },
});
// Filter by multiple enum values
const staff = await prisma.user.findMany({
where: {
role: { in: [Role.ADMIN, Role.MODERATOR] },
},
});
// Exclude enum value
const nonAdmins = await prisma.user.findMany({
where: {
role: { not: Role.ADMIN },
},
});Fix 2: Regenerate the Prisma Client After Schema Changes
After any change to schema.prisma, regenerate:
# Regenerate TypeScript types from schema
npx prisma generate
# Apply schema changes to database AND regenerate client
npx prisma migrate dev --name add-moderator-role
# Or for prototyping without migration history:
npx prisma db push
# Verify the generated types
cat node_modules/.prisma/client/index.d.ts | grep -A5 "enum Role"Full workflow when adding a new enum value:
// 1. Update schema.prisma
enum Role {
USER
ADMIN
MODERATOR // ← New value added
GUEST // ← Another new value
}# 2. Create and apply migration
npx prisma migrate dev --name "add-guest-and-moderator-roles"
# 3. Regenerate client (migrate dev does this automatically, but be explicit)
npx prisma generate
# 4. Restart TypeScript server in VS Code if types still look wrong
# Cmd+Shift+P → "TypeScript: Restart TS Server"Fix 3: Type-Safe Enum Handling in Application Code
Use Prisma’s generated enum type throughout your application:
// services/userService.ts
import { PrismaClient, Role, Prisma } from '@prisma/client';
const prisma = new PrismaClient();
// Function typed with Prisma enum
async function updateUserRole(userId: string, role: Role): Promise<void> {
await prisma.user.update({
where: { id: userId },
data: { role },
});
}
// Usage — TypeScript enforces valid enum values
await updateUserRole('user-123', Role.ADMIN); // OK
await updateUserRole('user-123', 'ADMIN'); // TypeScript error
await updateUserRole('user-123', Role.SUPERUSER); // TypeScript error (not in enum)
// Convert string to Prisma enum safely (e.g., from API input)
function parseRole(input: string): Role {
const valid = Object.values(Role) as string[];
if (!valid.includes(input)) {
throw new Error(`Invalid role: ${input}. Valid roles: ${valid.join(', ')}`);
}
return input as Role;
}
// In an API handler
app.put('/users/:id/role', async (req, res) => {
const { role } = req.body;
let parsedRole: Role;
try {
parsedRole = parseRole(role);
} catch (err) {
return res.status(400).json({ error: err.message });
}
await updateUserRole(req.params.id, parsedRole);
res.json({ success: true });
});Fix 4: Migrate Existing Enum Values
When renaming or removing enum values, you need a migration strategy:
// BEFORE
enum Status {
ACTIVE
INACTIVE
PENDING
}
// AFTER — renaming INACTIVE to DISABLED
enum Status {
ACTIVE
DISABLED // Was: INACTIVE
PENDING
}PostgreSQL — enum values can’t be renamed directly. Use a manual migration:
-- In a custom migration file:
-- Step 1: Add the new enum value
ALTER TYPE "Status" ADD VALUE 'DISABLED';
-- Step 2: Update existing data
UPDATE "User" SET status = 'DISABLED' WHERE status = 'INACTIVE';
-- Step 3: PostgreSQL doesn't support removing enum values directly
-- You need to recreate the type:
-- This is complex — consider keeping old values for backward compatibilitySimpler approach — keep old values, add new ones, deprecate old:
enum Status {
ACTIVE
INACTIVE // Keep for backward compatibility
DISABLED // New preferred value
PENDING
}# Just add the new value
npx prisma migrate dev --name "add-disabled-status"Fix 5: Enums in Raw Queries
When using prisma.$queryRaw, enum values must be cast explicitly:
// PostgreSQL raw query with enum
const users = await prisma.$queryRaw<User[]>`
SELECT * FROM "User" WHERE role = ${Role.ADMIN}::"Role"
`;
// PostgreSQL requires explicit cast ::"Role" for enum comparison
// Or use Prisma.sql tagged template
import { Prisma } from '@prisma/client';
const role = Role.ADMIN;
const users = await prisma.$queryRaw<User[]>(
Prisma.sql`SELECT * FROM "User" WHERE role = ${role}::"Role"`
);MySQL — enums are stored as strings, no cast needed:
// MySQL raw query
const users = await prisma.$queryRaw<User[]>`
SELECT * FROM User WHERE role = ${Role.ADMIN}
`;Fix 6: Enum in API Responses and Validation
Serialize enums correctly in API responses and validate input:
// Zod validation with Prisma enum
import { z } from 'zod';
import { Role } from '@prisma/client';
const UpdateRoleSchema = z.object({
role: z.nativeEnum(Role), // Validates against Prisma-generated enum
});
// Or build from enum values:
const RoleEnum = z.enum(Object.values(Role) as [string, ...string[]]);
// API handler with validation
app.put('/users/:id/role', async (req, res) => {
const result = UpdateRoleSchema.safeParse(req.body);
if (!result.success) {
return res.status(400).json({ errors: result.error.flatten() });
}
await prisma.user.update({
where: { id: req.params.id },
data: { role: result.data.role },
});
res.json({ success: true });
});Include enum in API response documentation:
// Expose available enum values via API
app.get('/meta/roles', (req, res) => {
res.json({
roles: Object.values(Role),
// Returns: ["USER", "ADMIN", "MODERATOR"]
});
});Still Not Working?
Prisma client out of date after node_modules reinstall — if you delete node_modules and reinstall, you must run prisma generate again. The generated client in node_modules/.prisma/client is not stored in git:
# Add to package.json scripts for automatic postinstall generation:
{
"scripts": {
"postinstall": "prisma generate"
}
}SQLite enum behavior — SQLite doesn’t have native enum types. Prisma stores enums as TEXT in SQLite. This means invalid string values won’t cause a database error — only Prisma’s client-side validation will catch them. Always use the generated enum object.
Prisma enum vs TypeScript native enum — don’t mix Prisma-generated enums with TypeScript enum declarations. They look similar but behave differently. Prisma generates a const object { USER: 'USER', ADMIN: 'ADMIN' }, not a TypeScript numeric enum.
For related Prisma issues, see Fix: Prisma Transaction Error and Fix: Prisma N+1 Query Problem.
Solo developer based in Japan. Every solution is cross-referenced with official documentation and tested before publishing.
Was this article helpful?
Related Articles
Fix: Prisma Transaction Error — Transaction Already Closed or Rolled Back
How to fix Prisma transaction errors — interactive transactions vs $transaction array, error handling and rollback, nested transactions, timeout issues, and isolation levels.
Fix: Prisma Unique Constraint Failed on the Fields
How to fix Prisma's 'Unique constraint failed on the fields' error — finding which field caused it, handling upserts, race conditions, and bulk insert deduplication.
Fix: Drizzle ORM Not Working — Schema Out of Sync, Relation Query Fails, or Migration Error
How to fix Drizzle ORM issues — schema definition, drizzle-kit push vs migrate, relation queries with, transactions, type inference, and common PostgreSQL/MySQL configuration problems.
Fix: Prisma Connection Pool Exhausted — Can't Acquire Connection from Pool
How to fix Prisma connection pool errors — pool size configuration, connection leaks, serverless deployments, singleton pattern, query timeout, and pgBouncer integration.