Skip to content

Fix: Prisma Enum Not Working — Invalid Enum Value or Enum Not Recognized

FixDevs ·

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 enumrole: 'ADMIN' is a string. Prisma expects role: 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 run prisma generate to regenerate the TypeScript types. Until then, the old types are in effect.
  • Migration not run — if you added a new enum value, prisma db push or prisma migrate dev must 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. ADMINadminAdmin.

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 compatibility

Simpler 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.

F

FixDevs

Solo developer based in Japan. Every solution is cross-referenced with official documentation and tested before publishing.

Was this article helpful?

Related Articles