Troubleshooting
Common issues and solutions when using nviron
Common Errors
Validation Errors
String Expected, Received Undefined
Error Message:
❌ Environment Variable Missing or Invalid
1. DATABASE_URL → Expected string, received undefinedCause: The environment variable is not defined in your .env file or environment.
Solution:
-
Check your
.envfile exists and contains the variable:DATABASE_URL=postgresql://localhost:5432/mydb -
Ensure you're loading environment variables correctly:
# If using dotenv node -r dotenv/config src/index.js -
For Next.js, restart your development server after adding new variables
-
Verify the variable name matches exactly (case-sensitive):
// Schema expects DATABASE_URL DATABASE_URL: z.string().url() // .env must have DATABASE_URL, not database_url DATABASE_URL=postgresql://...
Expected Number, Received String
Error Message:
❌ Environment Variable Missing or Invalid
1. PORT → Expected number, received stringCause: Using z.number() instead of z.coerce.number().
Solution:
Environment variables are always strings. Use coercion:
// ❌ Wrong
const env = defineEnv({
PORT: z.number(),
});
// ✅ Correct
const env = defineEnv({
PORT: z.coerce.number(),
});Invalid URL
Error Message:
❌ Environment Variable Missing or Invalid
1. DATABASE_URL → Invalid urlCause: The value is not a valid URL format.
Solution:
Ensure the URL is properly formatted:
# ❌ Wrong
DATABASE_URL=localhost:5432/mydb
# ✅ Correct
DATABASE_URL=postgresql://localhost:5432/mydbCommon URL issues:
- Missing protocol (
http://,https://,postgresql://) - Invalid characters or spaces
- Incorrect port format
- Missing slashes
String Must Contain at Least X Characters
Error Message:
❌ Environment Variable Missing or Invalid
1. JWT_SECRET → String must contain at least 32 character(s)Cause: The value doesn't meet the minimum length requirement.
Solution:
Generate a proper secret:
# Generate a secure 32+ character secret
openssl rand -base64 32
# Or use a password generator
# Ensure it's at least 32 charactersUpdate your .env:
JWT_SECRET=your-generated-secret-here-min-32-charsTypeScript Errors
Cannot Find Module 'nviron'
Error Message:
Cannot find module 'nviron' or its corresponding type declarations.Solution:
-
Ensure nviron is installed:
npm install nviron -
Check your
package.jsonincludes nviron:{ "dependencies": { "nviron": "^1.0.0" } } -
Restart your TypeScript server in your IDE
Type 'X' is Not Assignable to Type 'Y'
Error Message:
Type 'string | undefined' is not assignable to type 'string'.Cause: Using an optional value where a required value is expected.
Solution:
-
Handle the optional case:
const env = defineEnv({ REDIS_URL: z.string().url().optional(), }); // ❌ Wrong: Might be undefined const client = createClient(env.REDIS_URL); // ✅ Correct: Handle undefined const client = env.REDIS_URL ? createClient(env.REDIS_URL) : null; -
Or use a default value:
const env = defineEnv({ REDIS_URL: z.string().url().default("redis://localhost:6379"), }); // Now env.REDIS_URL is always a string const client = createClient(env.REDIS_URL);
Framework-Specific Issues
Next.js: Environment Variables Not Available
Problem: Environment variables work in development but not in production.
Solution:
-
For client-side variables, use the
NEXT_PUBLIC_prefix:# Client-side NEXT_PUBLIC_API_URL=https://api.example.com # Server-side only DATABASE_URL=postgresql://... -
Validate environment at build time in
next.config.mjs:import "./src/env.ts"; /** @type {import('next').NextConfig} */ const nextConfig = {}; export default nextConfig; -
For Vercel deployment, add environment variables in project settings
Vite: import.meta.env is Undefined
Problem: Using import.meta.env in Node.js context.
Solution:
Only use import.meta.env in Vite/browser code:
// ✅ Correct: In Vite project
const env = defineEnv(
{
API_URL: z.string().url(),
},
{
source: import.meta.env,
prefix: "VITE_",
},
);For server-side Vite (SSR):
// Use process.env for server-side
const env = defineEnv({
DATABASE_URL: z.string().url(),
});Express: process.env Variables Not Loading
Problem: Variables in .env file not being loaded.
Solution:
-
Install dotenv:
npm install dotenv -
Load environment variables early:
import "dotenv/config"; // Must be first import import { env } from "./env"; import express from "express"; -
Or use the
-rflag:node -r dotenv/config src/index.js
Prefix Issues
Variables Not Found with Prefix
Problem: Using prefix but variables still not found.
Solution:
Ensure your .env file uses the prefix:
// env.ts
const env = defineEnv(
{
API_URL: z.string().url(),
},
{
prefix: "VITE_",
},
);# .env - Must include prefix
VITE_API_URL=https://api.example.com
# ❌ Wrong - No prefix
API_URL=https://api.example.comPrefix Not Being Stripped
Problem: Accessing variables with prefix instead of without.
Cause: Misunderstanding how prefix works.
Explanation:
Nviron automatically strips the prefix:
const env = defineEnv(
{
API_URL: z.string().url(), // Schema key without prefix
},
{
prefix: "VITE_",
},
);
// Access WITHOUT prefix
console.log(env.API_URL); // ✅ Correct
console.log(env.VITE_API_URL); // ❌ Wrong - doesn't existCoercion Issues
Boolean Coercion Not Working
Problem: Boolean values not being converted properly.
Solution:
Understand valid boolean string values:
# ✅ These work
ENABLE_FEATURE=true
ENABLE_FEATURE=false
ENABLE_FEATURE=1
ENABLE_FEATURE=0
ENABLE_FEATURE=yes
ENABLE_FEATURE=no
# ❌ These don't work
ENABLE_FEATURE=enabled # Not a valid boolean string
ENABLE_FEATURE=TRUE # Case sensitiveUse in schema:
const env = defineEnv({
ENABLE_FEATURE: z.coerce.boolean(),
});Number Coercion Failing
Problem: Number conversion fails with valid-looking numbers.
Cause: Invalid number format or special characters.
Solution:
# ✅ Valid
PORT=3000
MAX_SIZE=1000000
# ❌ Invalid
PORT=3,000 # No commas
PORT=3000px # No units
PORT=three # Must be numeric
PORT=3.0.0 # Not a valid numberDate Coercion Issues
Problem: Date coercion not working as expected.
Solution:
Use ISO 8601 date format:
# ✅ Valid formats
CREATED_AT=2024-01-15
CREATED_AT=2024-01-15T10:30:00Z
CREATED_AT=2024-01-15T10:30:00+00:00
# ❌ Invalid formats
CREATED_AT=15/01/2024
CREATED_AT=Jan 15 2024
CREATED_AT=1642247400 # Use z.coerce.number() then transformValidation Issues
Custom Validation Not Working
Problem: Refinement rules not being applied.
Solution:
Ensure you're using .refine() correctly:
// ✅ Correct
const env = defineEnv({
DATABASE_URL: z
.string()
.url()
.refine((url) => url.startsWith("postgresql://"), {
message: "Must be a PostgreSQL URL",
}),
});
// ❌ Wrong - refine returns undefined
const env = defineEnv({
DATABASE_URL: z
.string()
.url()
.refine(
(url) => url.startsWith("postgresql://"), // Missing return
),
});Transform Not Applied
Problem: Transformed values not working as expected.
Solution:
Understand transform order:
const env = defineEnv({
// Transforms happen after validation
ALLOWED_ORIGINS: z
.string()
.min(1) // Validates first
.transform((val) => val.split(",")) // Then transforms
.refine((arr) => arr.length > 0, {
// Then refines
message: "At least one origin required",
}),
});Performance Issues
Slow Application Startup
Problem: Application takes too long to start.
Cause: Complex validations or too many environment variables.
Solution:
-
Simplify validation rules:
// ❌ Slow: Complex regex API_KEY: z.string().regex(/^[A-Za-z0-9_-]{32,256}$/); // ✅ Faster: Simple length check API_KEY: z.string().min(32).max(256); -
Use a singleton pattern:
// env.ts - Created once export const env = defineEnv({ ... });
Memory Usage
Problem: High memory usage from environment validation.
Solution:
Ensure you're not creating multiple instances:
// ❌ Wrong: New instance every import
export function getEnv() {
return defineEnv({ ... });
}
// ✅ Correct: Single instance
export const env = defineEnv({ ... });Development vs Production
Works in Development, Fails in Production
Problem: Validation passes locally but fails in production.
Causes & Solutions:
-
Missing environment variables
- Add all required variables to your production environment
- Use your hosting provider's environment variable settings
-
Different defaults
// Make critical values required const env = defineEnv({ DATABASE_URL: z.string().url(), // No default JWT_SECRET: z.string().min(32), // No default }); -
Case sensitivity
# Development (Windows - case insensitive) database_url=postgresql://... # Production (Linux - case sensitive) DATABASE_URL=postgresql://... # Must match exactly
Production Builds Failing
Problem: Build fails during CI/CD.
Solution:
-
Set environment variables in CI/CD:
# GitHub Actions example env: DATABASE_URL: ${{ secrets.DATABASE_URL }} JWT_SECRET: ${{ secrets.JWT_SECRET }} -
Use build-time validation for Next.js:
// next.config.mjs import "./src/env.ts"; // Validates during build -
Provide test values for CI:
# .env.ci DATABASE_URL=postgresql://test:test@localhost:5432/test JWT_SECRET=test-secret-for-ci-only-32-chars
Debugging
Enable Debug Mode
See what's happening during validation:
import { defineEnv, z } from "nviron";
// Temporarily log values for debugging
const schema = {
PORT: z.coerce.number(),
DATABASE_URL: z.string().url(),
};
console.log("Environment source:", process.env);
console.log("Schema keys:", Object.keys(schema));
const env = defineEnv(schema);
console.log("Validated env:", env);Check Environment Loading
Verify environment variables are being loaded:
// Check if .env is loaded
console.log("NODE_ENV:", process.env.NODE_ENV);
console.log("All env vars:", Object.keys(process.env));
// Check specific variable
console.log("DATABASE_URL exists:", "DATABASE_URL" in process.env);
console.log("DATABASE_URL value:", process.env.DATABASE_URL);Validate Step by Step
Debug validation by testing individual variables:
import { z } from "nviron";
// Test individual validations
try {
z.coerce.number().parse(process.env.PORT);
console.log("✅ PORT is valid");
} catch (error) {
console.error("❌ PORT validation failed:", error);
}
try {
z.string().url().parse(process.env.DATABASE_URL);
console.log("✅ DATABASE_URL is valid");
} catch (error) {
console.error("❌ DATABASE_URL validation failed:", error);
}Getting Help
If you're still experiencing issues:
- Check the documentation - Review relevant sections
- Search existing issues - Someone may have had the same problem
- Create a minimal reproduction - Isolate the issue
- Open an issue - Provide:
- Environment (Node version, framework, OS)
- Minimal code example
- Error message
- Expected vs actual behavior
For more help, visit the GitHub Issues page.