Netlify: env vars not loading in functions [2026 fix]
Environment variables undefined in Netlify Functions? Your functions.toml is missing or vars aren't deployed—redeploy with netlify deploy --prod.
Netlify: env vars not loading in functions [2026 fix]
TL;DR
Cause: Environment variables defined in Netlify UI aren't automatically injected into function runtime without explicit configuration or deployment trigger. Fix: Createnetlify.toml with [functions] config and redeploy with netlify deploy --prod.---
Real Console Error Messages
``` Error: undefined is not a function at Object.<anonymous> (/var/task/my-function.js:5:12) at Module._load (internal/modules/esm_loader.js:1043:23) ```
``` TypeError: Cannot read property 'apiKey' of undefined at handler (/var/task/functions/fetch-data.js:15:8) ```
``` ReferenceError: process.env.DATABASE_URL is not defined at exports.handler (/var/task/api/query.js:22:5) ```
``` Function invocation failed: Error loading module: SyntaxError in handler code near line 1: ReferenceError: process.env.STRIPE_KEY === undefined ```
``` 502 Bad Gateway x-nf-request-id: a1b2c3d4-e5f6-7890 Function returned an error: process.env.API_ENDPOINT is null ```
---
Broken Code vs. Fixed Code
❌ Broken: Missing netlify.toml Configuration
```javascript
// functions/fetch-user.js
exports.handler = async (event) => {
const apiKey = process.env.API_KEY; // ← undefined at runtime
const response = await fetch(https://api.example.com/user, {
headers: { "Authorization": Bearer ${apiKey} }
});
return {
statusCode: 200,
body: JSON.stringify(await response.json())
};
};
```
Problem: You set API_KEY in Netlify UI (Site settings → Build & deploy → Environment), but functions don't receive it without explicit config.
✅ Fixed: Proper netlify.toml + Redeploy
Step 1: Create/Update netlify.toml in repo root
```toml [functions] node_bundler = "esbuild"
[[context.production.environment]] API_KEY = "$API_KEY" DATABASE_URL = "$DATABASE_URL" STRIPE_KEY = "$STRIPE_KEY" ```
OR (simpler approach for most cases):
```toml [functions] node_bundler = "esbuild" ```
Then keep vars ONLY in Netlify UI (Site settings → Build & deploy → Environment), but ensure you:
Step 2: Redeploy with explicit flag
```bash
From repo root
netlify deploy --prod ```OR push to your connected branch (main/develop) and let Netlify's CI trigger the build.
Step 3: Function code stays the same
```javascript
// functions/fetch-user.js (no changes needed!)
exports.handler = async (event) => {
const apiKey = process.env.API_KEY; // ← NOW defined
const response = await fetch(https://api.example.com/user, {
headers: { "Authorization": Bearer ${apiKey} }
});
return {
statusCode: 200,
body: JSON.stringify(await response.json())
};
};
```
What changed: Only the deployment method and config. The runtime now has access to env vars.
---
Why This Happens
Netlify Functions read environment variables from three sources (in priority order):
1. netlify.toml [context.*.environment] section
2. Netlify UI Environment variables (Site settings)
3. .env.production local file (for local testing only)
If your netlify.toml is missing *and* you haven't redeployed since adding vars to the UI, functions run with a stale environment snapshot.
---
Still broken? Check these too
1. Mixed Node versions: If you specify node_bundler = "esbuild" but use CommonJS require() instead of import, syntax errors occur. Verify your function uses compatible syntax for the bundler. [See Node.js runtime guide](/?guide=netlify-node-versions).
2. Caching issue: Clear Netlify's build cache. Go to Site settings → Builds & deploy → Clear cache and retry the deploy. Sometimes stale artifacts block env injection.
3. Function format mismatch: Ensure functions are in netlify/functions/ directory (not functions/ at root unless configured differently in netlify.toml with directory property). Check [build.functions] path in your config file. [Reference on function placement](/?guide=netlify-function-paths).
---
Official Resources
---
Quick Checklist
netlify.toml exists with [functions] sectionnetlify/functions/ directorynetlify deploy --prod (or pushed to connected branch)---
Found a different variation? Drop it in the comments.