Netlify: env vars not loading in functions [2026 fix]
Env vars undefined in Netlify Functions? Missing netlify.toml config or runtime mismatch. Add [[functions]] block with node_bundler setting.
Netlify: env vars not loading in functions [2026 fix]
TL;DR
Cause: Yournetlify.toml lacks function configuration or uses incompatible Node bundler settings.
Fix: Add [[functions]] block specifying node_bundler = "esbuild" and redeploy.---
Real Console Error Messages
``` Error: process.env.DATABASE_URL is undefined at Object.<anonymous> (/var/task/functions/api.js:12:5) at Module._load (node:internal/modules/require_cache:js:165:29) ```
``` ReferenceError: Cannot read property 'DATABASE_URL' of undefined at handler (/var/task/src/functions/query.js:8:23) ```
``` [Functions] Error during execution: unable to resolve "process.env.API_KEY" ```
``` Warning: dotenv did not load in production Your environment variables are empty {} ```
``` TypeError: Cannot destructure property 'API_SECRET' of 'undefined' at Object.<anonymous> (functions/auth.js:1:1) ```
---
The Problem Explained
Netlify Functions in production don't automatically inject environment variables the way your local dev server does. The issue stems from one of three causes:
1. Missing netlify.toml configuration – Functions aren't told where to find env vars
2. Node bundler incompatibility – Using webpack instead of esbuild prevents proper variable tree-shaking
3. Runtime environment mismatch – Local Node 16 vs. Netlify's Node 18/20 handle dotenv differently
---
Broken vs. Fixed Code
Scenario 1: No netlify.toml Configuration
BROKEN: ```toml
netlify.toml (missing function config)
[build] command = "npm run build" functions = "netlify/functions" ```FIXED: ```toml
netlify.toml
[build] command = "npm run build" functions = "netlify/functions"[[functions]] node_bundler = "esbuild" environment = { DATABASE_URL = "$DATABASE_URL", API_KEY = "$API_KEY" } ```
Scenario 2: Incorrect Env Var Access in Function
BROKEN: ```javascript // netlify/functions/api.js const { DATABASE_URL } = process.env;
exports.handler = async (event) => { const conn = await connect(DATABASE_URL); // undefined! return { statusCode: 500 }; }; ```
FIXED: ```javascript // netlify/functions/api.js exports.handler = async (event) => { const DATABASE_URL = process.env.DATABASE_URL; if (!DATABASE_URL) { return { statusCode: 500, body: JSON.stringify({ error: "DATABASE_URL not set" }) }; } const conn = await connect(DATABASE_URL); return { statusCode: 200 }; }; ```
Scenario 3: Netlify UI Environment Variables Not Set
BROKEN: ```bash
Netlify Dashboard shows no env vars in Site Settings > Build & Deploy > Environment
Or vars are named differently than in code
```FIXED: ```bash
In Netlify Dashboard:
1. Go to Site Settings → Build & Deploy → Environment
2. Click "Edit variables"
3. Add: DATABASE_URL = "your_actual_db_url"
4. Add: API_KEY = "your_actual_key"
5. Redeploy the site (or trigger new deployment)
```---
Step-by-Step Fix
1. Check netlify.toml exists in repo root: ```bash cat netlify.toml ```
2. Add or update the functions section: ```toml [[functions]] node_bundler = "esbuild" ```
3. Verify env vars in Netlify Dashboard: - Site Settings → Build & Deploy → Environment Variables - Ensure all vars referenced in code are listed
4. Access safely in code: ```javascript const key = process.env.API_KEY || "fallback_value"; ```
5. Redeploy: ```bash git push origin main ```
6. Check deployment logs (Netlify Dashboard → Deploys → latest) for errors.
---
Still broken? Check these too
Issue #1: Function not triggering at all
netlify/functions/ directoryapi.js → /.netlify/functions/api)Issue #2: Env vars work locally but not in production
process.env not import.meta.env (that's Vite-specific)Issue #3: Timeout or permission denied errors
---
Version Note
This guide applies to Netlify's current runtime (Node 18+, esbuild default as of 2026). If you're on older Netlify builds,webpack was the default bundler—explicitly set node_bundler = "esbuild" to upgrade behavior.---
Official Resources
---
Found a different variation? Drop it in the comments.