Skip to content

🐛 BUG: env.process.NODE_ENV returns 'undefined' in Cloudflare Workers #9802

@MrChrisRodriguez

Description

@MrChrisRodriguez

What versions & operating system are you using?

Wrangler 4.22.0, Node v20.19.2

Please provide a link to a minimal reproduction

https://github.com/Confiador/cf-worker-node-env

Describe the Bug

Environment:

  • Runtime: Cloudflare Workers (via Wrangler) run locally
  • Development server: wrangler dev --ip=127.0.0.1 --env development --port 1234

Issue Description:
The NODE_ENV environment variable cannot be accessed using standard JavaScript property access methods (process.env.NODE_ENV or process.env['NODE_ENV']), despite being present in the environment and accessible through other means.

Expected Behavior:
process.env.NODE_ENV should return 'development'

Actual Behavior:
process.env.NODE_ENV returns the string undefined.

Evidence:

// All of these show NODE_ENV exists:
console.log(process.env); // Shows: { NODE_ENV: 'development', ... }
Object.keys(process.env); // Includes 'NODE_ENV'
'NODE_ENV' in process.env; // Returns true
Object.getOwnPropertyDescriptor(process.env, 'NODE_ENV'); // Shows { value: 'development', ... }

// But standard access fails:
process.env.NODE_ENV; // Returns undefined
process.env['NODE_ENV']; // Returns undefined

// Only Reflect.get() works:
Reflect.get(process.env, 'NODE_ENV'); // Returns 'development'

Key Details:

  • Other environment variables work correctly with all access methods
  • The issue is specific to NODE_ENV
  • Property descriptor shows the value exists and is accessible
  • Reflect.get() successfully retrieves the correct value

Root Cause:
Appears to be a bug in Cloudflare Workers' process.env Proxy implementation where the get trap has faulty handling specifically for the NODE_ENV property.

Workaround:
Use Reflect.get(process.env, 'NODE_ENV') instead of direct property access.

Please provide any relevant error logs

(base) cf-worker-node-env % wrangler dev --ip=127.0.0.1 --env development --port 1234

 ⛅️ wrangler 4.22.0
───────────────────
Your Worker has access to the following bindings:
Binding                           Resource                  Mode
env.NODE_ENV ("development")      Environment Variable      local

╭──────────────────────────────────────────────────────────────────────╮
│  [b] open a browser [d] open devtools [c] clear console [x] to exit  │
╰──────────────────────────────────────────────────────────────────────╯
⎔ Starting local server...
[wrangler:info] Ready on http://127.0.0.1:1234

============================================================
🐛 CLOUDFLARE WORKERS NODE_ENV BUG REPRODUCTION

📋 SECTION 1: Verify NODE_ENV exists in environment
Full process.env object: { NODE_ENV: 'development' }
Keys in process.env: [ 'NODE_ENV' ]
NODE_ENV in process.env keys? true

🔍 SECTION 2: Property existence checks
'NODE_ENV' in process.env: true
process.env.hasOwnProperty('NODE_ENV'): true
Object.getOwnPropertyNames includes NODE_ENV: true

🔬 SECTION 3: Property descriptor analysis
NODE_ENV property descriptor: {
value: 'development',
writable: true,
enumerable: true,
configurable: true
}

  • value: development
  • writable: true
  • enumerable: true
  • configurable: true

❌ SECTION 4: BUG DEMONSTRATION - Standard access fails
process.env.NODE_ENV: undefined
process.env['NODE_ENV']: undefined
Expected: 'development' (or current NODE_ENV value)
Actual: undefined

✅ SECTION 5: WORKAROUND - Reflect.get works
Reflect.get(process.env, 'NODE_ENV'): development
This correctly returns the NODE_ENV value!

🆚 SECTION 6: Comparison with other env vars

🔧 SECTION 7: Additional debugging info
typeof process.env: object
process.env constructor: Object
Is process.env a Proxy? true

============================================================
🏁 END OF BUG REPRODUCTION

[wrangler:info] GET / 200 OK (8ms)

Metadata

Metadata

Labels

bugSomething that isn't working

Type

Projects

Status

Untriaged

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions