Strict Mode Configuration
The strict mode feature provides granular control over when .strict()
is applied to generated Zod schemas. By default, all schemas include .strict()
for backward compatibility, but you can now configure this behavior globally, per-model, per-operation, or per-variant.
Overview
Zod's .strict()
method prevents unknown properties from being accepted during validation. While this provides type safety, there are scenarios where you might want more flexible validation:
- API integration: External APIs might return additional fields
- Gradual migration: Transitioning from loose to strict validation
- Development flexibility: Allowing extra fields during development
Global Configuration
Configure strict mode globally for all schemas:
{
"strictMode": {
"enabled": true, // Global default for all schemas
"operations": true, // CRUD operation schemas (findMany, create, etc.)
"objects": true, // Input object schemas (WhereInput, CreateInput, etc.)
"variants": true // Variant schemas (pure, input, result)
}
}
Default Behavior
Without any strictMode
configuration, all schemas include .strict()
for backward compatibility:
// Default behavior
export const UserCreateInputSchema = z.object({
name: z.string(),
email: z.string()
}).strict(); // ← Applied by default
Disabling Globally
To disable strict mode for all schemas:
{
"strictMode": {
"enabled": false
}
}
// Result: no .strict() suffix
export const UserCreateInputSchema = z.object({
name: z.string(),
email: z.string()
}); // ← No .strict()
Schema Type Control
Control strict mode for specific schema types:
{
"strictMode": {
"enabled": true,
"operations": true, // findMany, create, update operations
"objects": false, // WhereInput, CreateInput objects
"variants": true // Pure, input, result variants
}
}
This configuration results in:
// Operations: strict (operations: true)
export const FindManyUserArgsSchema = z.object({
where: UserWhereInputSchema.optional()
}).strict(); // ← Has .strict()
// Objects: not strict (objects: false)
export const UserWhereInputSchema = z.object({
name: z.string().optional()
}); // ← No .strict()
// Variants: strict (variants: true)
export const UserPureSchema = z.object({
id: z.number(),
name: z.string()
}).strict(); // ← Has .strict()
// Enums: always strict (inherently strict, no .strict() method)
export const StatusSchema = z.enum(['ACTIVE', 'INACTIVE']); // ← No .strict() needed
Model-Level Configuration
Override strict mode settings for specific models:
{
"strictMode": {
"enabled": true,
"operations": false,
"objects": false
},
"models": {
"User": {
"strictMode": {
"enabled": true, // Enable for User model
"operations": true, // Override: User operations get .strict()
"objects": true // Override: User objects get .strict()
}
},
"Post": {
"strictMode": {
"enabled": false // Disable all strict mode for Post
}
}
}
}
Result:
- User: All schemas get
.strict()
(model override) - Post: No schemas get
.strict()
(model disabled) - Other models: Follow global settings (operations and objects disabled)
Operation-Level Control
Control strict mode for specific operations within a model:
{
"models": {
"User": {
"strictMode": {
"operations": ["findMany", "create"], // Only these operations get .strict()
"exclude": ["update"] // Exclude update operations
}
}
}
}
// Gets .strict() (in operations list)
export const FindManyUserArgsSchema = z.object({...}).strict();
// Gets .strict() (in operations list)
export const CreateOneUserArgsSchema = z.object({...}).strict();
// No .strict() (not in operations list)
export const UpdateOneUserArgsSchema = z.object({...});
// No .strict() (in exclude list)
export const UpdateManyUserArgsSchema = z.object({...});
Operation Names
Valid operation names include:
findUnique
,findUniqueOrThrow
findFirst
,findFirstOrThrow
findMany
create
,createMany
,createManyAndReturn
update
,updateMany
,updateManyAndReturn
delete
,deleteMany
upsert
aggregate
,groupBy
,count
Variant-Level Control
Configure strict mode for specific variants:
Global Variant Settings
{
"strictMode": {
"variants": false // Disable for all variants globally
},
"variants": {
"pure": {
"enabled": true,
"strictMode": true // Override: pure variants get .strict()
},
"input": {
"enabled": true,
"strictMode": false // Explicit: input variants don't get .strict()
},
"result": {
"enabled": true
// Uses global variants setting (false)
}
}
}
Model-Specific Variant Settings
{
"models": {
"User": {
"strictMode": {
"variants": {
"pure": true, // User pure variant gets .strict()
"input": false, // User input variant doesn't get .strict()
"result": null // Uses global/parent setting
}
}
}
}
}
Configuration Hierarchy
Strict mode settings follow a hierarchy (most specific wins):
- Operation-level (
models.ModelName.strictMode.operations
array) - Model-level (
models.ModelName.strictMode.*
) - Global schema type (
strictMode.operations
,strictMode.objects
, etc.) - Global default (
strictMode.enabled
)
Example Hierarchy
{
"strictMode": {
"enabled": false, // 4. Global default: disabled
"operations": true // 3. Global operations: enabled
},
"models": {
"User": {
"strictMode": {
"enabled": true, // 2. Model-level: enabled
"operations": ["findMany"] // 1. Operation-level: only findMany
}
}
}
}
Result for User model:
findMany
: strict (operation-level wins)create
: not strict (not in operation list)objects
: strict (inherits from model-level enabled)
Common Patterns
API-Friendly Configuration
Disable strict mode for operations but keep it for internal schemas:
{
"strictMode": {
"enabled": true,
"operations": false, // Allow extra fields in API requests
"objects": true, // Keep strict for internal validation
"variants": true
}
}
Development vs Production
Development configuration (more permissive):
{
"strictMode": {
"enabled": false,
"operations": false,
"objects": false,
"variants": true // Keep variants strict for type safety
}
}
Production configuration (strict validation):
{
"strictMode": {
"enabled": true,
"operations": true,
"objects": true,
"variants": true
}
}
Gradual Migration
Start with loose validation and gradually enable strict mode:
{
"strictMode": {
"enabled": false // Start permissive
},
"models": {
"User": {
"strictMode": {
"enabled": true // Migrate User model first
}
}
}
}
Backward Compatibility
The strict mode feature maintains full backward compatibility:
- No configuration: All schemas get
.strict()
(existing behavior) - Existing projects: Continue working without changes
- New projects: Can opt into flexible validation
Examples
Basic Usage
Disable strict mode for all operations but keep it for objects:
{
"strictMode": {
"enabled": true,
"operations": false,
"objects": true
}
}
Advanced Model Configuration
Different strict mode settings per model:
{
"strictMode": {
"enabled": false,
"operations": false,
"objects": false
},
"models": {
"User": {
"strictMode": {
"enabled": true,
"operations": ["findMany", "create"],
"objects": true,
"variants": {
"pure": true,
"input": false
}
}
},
"Post": {
"strictMode": {
"operations": true,
"exclude": ["update", "delete"]
}
}
}
}
Variant-Specific Configuration
{
"strictMode": {
"enabled": true,
"variants": false
},
"variants": {
"pure": {
"enabled": true,
"strictMode": true
},
"input": {
"enabled": true,
"strictMode": false
}
},
"models": {
"User": {
"strictMode": {
"variants": {
"result": true
}
}
}
}
}
Migration Guide
From Always Strict (Default)
If you're upgrading and want to maintain existing behavior, no changes are needed. All schemas will continue to include .strict()
.
To Flexible Validation
To allow extra fields in API requests:
{
"strictMode": {
"operations": false, // Allow extra fields in operation inputs
"objects": true // Keep strict for internal objects
}
}
Per-Model Migration
Migrate models gradually:
{
"strictMode": {
"enabled": true // Keep existing strict behavior
},
"models": {
"NewModel": {
"strictMode": {
"operations": false // New model allows extra fields
}
}
}
}
Best Practices
- Start Conservative: Begin with strict mode enabled and selectively disable where needed
- Test Thoroughly: Validate that your application handles extra fields correctly when strict mode is disabled
- Document Decisions: Comment your configuration to explain why certain models/operations have different strict mode settings
- Environment-Specific: Consider different configurations for development vs production
- Gradual Migration: When changing existing projects, migrate model by model rather than all at once
Troubleshooting
Schemas Still Have .strict()
Check the configuration hierarchy. More specific settings override general ones:
{
"strictMode": {
"enabled": false // This might be overridden
},
"models": {
"User": {
"strictMode": {
"enabled": true // This overrides the global setting
}
}
}
}
Configuration Not Applied
- Ensure your configuration file is properly referenced in the Prisma schema
- Check for JSON syntax errors
- Verify the configuration file path is correct
- Run generation again after configuration changes
Unexpected Behavior
- Model not found: Ensure model names match exactly (case-sensitive)
- Operation not working: Check operation names against the valid list above
- Variant issues: Verify variant is enabled before configuring strict mode