NODE_ENV is undefined in lambda functions no matter what I do

I am setting up Sentry messages and need to access the NODE_ENV and the COMMIT_REF env vars in functions. However, all of them, including the CONTEXT are undefined both at build time and runtime. Although env vars that I set in the UI are available as expected.

const webpack = require(‘webpack’);
module.exports = {
mode: process.env.NODE_ENV === ‘production’ ? ‘production’ : ‘development’,
plugins: [
new webpack.DefinePlugin({
‘global.GENTLY’: false,
‘process.env.COMMIT_REF’: JSON.stringify(process.env.COMMIT_REF),
‘process.env.CONTEXT’: process.env.CONTEXT,
}),
],
};

I tried with a custom webpack.config.js:

const webpack = require('webpack');

module.exports = {
  mode: process.env.NODE_ENV === 'production' ? 'production' : 'development',
  plugins: [
    new webpack.DefinePlugin({
      'global.GENTLY': false,
      'process.env.COMMIT_REF': JSON.stringify(process.env.COMMIT_REF),
      'process.env.CONTEXT': process.env.CONTEXT,
    }),
  ],
};

and in the package.json
"build:lambda": "netlify-lambda build --config ./webpack.config.js ./lambda",

but this did not help.

I also tried to set env files in the netlify.toml and a bunch of other ways that did not work. It’s ridiculous that such a simple and much needed feature does not work out of the box and there is no documentation on how to make it work.

Any help appreciated!

Hey @sandorTuranszky :wave:t2:

I think I’ve got an answer for you :slight_smile: Ultimately I believe the root cause of what you’re facing is the strong split between environments - the Netlify Site Build environment, and the AWS Lambda Functions runtime environment. Not much gets shared between them by default.

So to walk through a flow a bit here, I’d say read this whole page to get a feel for what vars are available and such:

Then check out this build plugin that I think will help you out greatly

And in general, find more information about Build Plugins (which are super new! yay!) here:

That ought to do it!


Jon

Jon has as usual done an incredible job of providing a very similar answer to the one Netlify’s staff would have. The “missing piece” is one we’re working on writing up right now - TL;DR we only automatically “forward” environment variables from our UI, NOT from netlify.toml (nor automatically set like “$COMMIT_REF”), to functions. The plugin Jon linked is a good way to get there, or you can manually interpolate the variables as explained in this article:

1 Like

Thanks for the info. I understand that env variables are not available at runtime, but the thing is that they are not available at build time too. I found articles where webpack was used to further forward env vars but since they were undefined at built time, there was nothing to be forwarded. Here is the list of env vars which are undefined at build time and runtime for me. I also set context env in the netlify.toml file and none of them was available. This is confusing as I rely on documentation but it doesn’t work for me :frowning:

I will try all methods mentioned in this tread. Btw, I tried netlify-plugin-inline-functions-env which did not help. Maybe it’s because I installed it from the UI rather than in the netlify.toml file?

Hey @sandorTuranszky!

Happy to dig into this more but I think I may need you to share some code at this point because it’ll be tricky to get super-specific without seeing the actual nuts and bolts. This is all going to be about your build process - specifically the site-build process before the Functions get packaged and compressed down into their own files and sent off to AWS.

Could you share some of your Netlify.toml and Package.json files? I think that’ll give a good idea of what’s running when for starters :thinking:


Jon

1 Like

Hmm. They definitely ARE available at build time - I think you may need to reread the article I linked that shows you how to USE them at build time :slight_smile: But TL;DR having a process.env.X in your DEPLOYED javascript isn’t using them at build time. Having it run during build, and interpolating the value, is using them as I recommend.

If that doesn’t work, I’ll echo Jon that we could use to see how your code uses them and learn a bit about your deployment process to understand where the disconnect is.

Hi sandorTuranszky, did you find any solution?
I’m struggling to set my env vars for production, staging, and development.
I’ve tried different ways but it does not seem to work

Any help would be appreciated
Thanks

I actually ended up writing a pretty long post about env vars across multiple environments with Functions. I’d recommend giving it a thorough read :slight_smile:


Jon

1 Like

Thanks for that excellent post. I followed it and for some reason, I’m still unable to get it to work.
Im using netlify-plugin-contextual-env
My netlify.toml file is

[build]  
  command = "npm run build"
  functions = "build-lambda"
  publish = "build"
[[plugins]]
package = 'netlify-plugin-contextual-env'  
  [plugins.inputs]
  mode = 'prefix'

I have a simple lambda function

//envir.js
    exports.handler = async (event, context) => {
      const key = process.env.API_KEY;
      return {
        statusCode: 200,
        body: JSON.stringify({
          key,
        }),
      };
    };

In netlify settings I have

It seems to work because at build time I have the following logs

production:
image

branch:
image

but when I access the function either from the for production or branch it always returns the initial value of API_KEY
image

Am I missing anything?

I really appreciate any hint or solution for this topic

Thanks

Hey @moiscye

So everything server-side appears to be in working order, but going back over my own blog post, I think you may be crossing some wires. The post describes two separate ways of handling your ENV vars, but you have to follow just one — they don’t work ‘together’. By using netlify-plugin-contextual-env you’re telling me that you went with Route 1 from the article but Route 1 means that you’d only need API_KEY, BRANCH_DEPLOY_API_KEY and DEPLOY_PREVIEW_API_KEY.

You would only use DEV_API_KEY and PRODUCTION_API_KEY if you were going with Route 2 from the article, in which case you’d use the other build plugin and need a little bit of boilerplate at the top of your Function.

Since you’re going with Route 1, it is indeed correct behavior that your production function is using the (bare) API_KEY value.

I’d give the article another read and really isolate Route 1 from Route 2. They’re totally separate approaches.

Hope that helps!


Jon

Hi @jonsully,

I tried both routes in isolation. I just didn’t remove the DEV_API_KEY from netlify. Route 2 seemed to work as well but once deployed it will not change the value of the env vars.

netlify-plugin-contextual-env works for production as follows:

  • A production context would automatically set DATABASE_URL to the value of PRODUCTION_DATABASE_URL if it exists.

At the moment I have to deploy two different sites. One for staging and another for master but it’s kind of annoying. With other providers, it was a piece of cake doing this.

Regards,
Moises

To one of your points — it should be noted that simply changing an ENV var’s value in the UI won’t actually do anything. A new site build has to occur for those new ENV var values to be used. Additionally, and a fine point to be very aware of, for Functions to update with the new ENV var values, they need to be re-packaged. Functions only get repackaged when there’s a diff between the previous version and the new version… so I recommend folks add some kind of console.log() or something to their Function to ensure there’s a diff and the Function gets re-packaged (with the new ENV vars).

Yes, handling ENV vars with Netlify is different than some other providers… but then, Netlify is different that most providers anyway :stuck_out_tongue: Netlify is built around having a build stage where everything within a site’s code gets built, compiled, packaged, and sent off to either the Edge (CDN) or AWS Lambda. That packaging includes in-lining all the ENV vars. But that’s a good thing — if your site or Functions had to look up ENV vars every time they were called, you wouldn’t be able to run either as high-performance as they do. A little complex? Yes. Worth it in performance? I think so.


Jon