Netlify global in functions v2

The documentation for functions since v2 says that there is a Netlify global object, and that this object has an env field for getting environment variables. However, when my function attempts to use the Netlify.env interface I get a reference error:

"ReferenceError: Netlify is not defined"

indicating that the Netlify object is probably absent. Is the documentation incorrect?

This is supposed to be fixed: fix: make Netlify.env working by injecting it in the entry file by lukasholzer · Pull Request #1618 · netlify/zip-it-and-ship-it (github.com), which has since been added in this version: Release functions-utils: v5.2.37 · netlify/build (github.com).

I think it would be released in the coming week. Let us know if not.

Any progress on this? I’m still seeing the issue.

Are you sure you’re using v2 API? It won’t be available in the Lambda API.

I’m certain. I re-engineered existing functions to export default, receive Request objects and return Response objects. If I was on old functions they’d throw an error very quickly (upon using the headers interface). They otherwise work exactly as v2 functions are documented. There’s simply no Netlify global object. I am, however, able to use the Node.js process.env global.

Edit: To be clear, these functions are in production and do the job they’re supposed to do. I rely on global access to environment variables though, so I’m using a wrapper function which attempts to get environment variables from Netlify.env(...), or falls back to process.env[...] (logging whichever worked). The logs from this are how I know there’s still a problem with Netlify.env. You can see that wrapper here (not my finest code, be kind).

Interesting. I have asked the devs to take another look.

Hey @qubyte, thanks for reporting this! I looked into it, and was able to reproduce it with this function:

const bar = Netlify.env.get("FOO")

export default () => {
  return new Response(bar);
};

export const config = { path: "/*" };

interestingly, this function works:

- const bar = Netlify.env.get("FOO")

export default () => {
-  return new Response(bar);
+  return new Response(Netlify.env.get("FOO"));
};

export const config = { path: "/*" };

So the problem seems to be that user code is being evaluated, before our system code populates the Netlify global. I’ll look into how we can fix that!

Currently seeing this issue

Interesting! I forgot to report back, but we fixed the original issue a couple days after my last post. Are you seeing this with the Netify CLI locally, or when Netlify builds it for you? If it’s the CLI, what version are you on and does it still exist with the latest CLI version? Could you share the function code you’re seeing this error on?

Seems to work perfectly locally!

Here’s what I’m seeing in prod in the console…

Feb 11, 07:31:02 PM: fc36f5d7 ERROR Invoke Error {
“errorType”:“ReferenceError”,
“errorMessage”:“Netlify is not defined”,
“stack”:[
“ReferenceError: Netlify is not defined”,
" at Runtime.handler (/var/task/netlify/functions/…
at Runtime.handleOnceNonStreaming (file:///var/runtime/index.mjs:1173:29)
"
]
}

And on screen:

This function has crashed

An unhandled error in the function code triggered the following message:

ReferenceError - Netlify is not defined

Stack trace

ReferenceError: Netlify is not defined
    at Runtime.handler (/var/task/netlify/functions/...
    at Runtime.handleOnceNonStreaming (file:///var/runtime/index.mjs:1173:29)

Connection details

Netlify internal ID: 01HPFQME6RSB7E35339JFD4A7T

Colin, could you share the Function code for this request? That should help me reproduce.

Also, the Netlify global only exists in Functions 2.0, and the stacktrace you mention makes me think you’re using Lambda Compatibility mode aka “old functions”. Could that be the case?

Yes, thanks for the help! Works perfectly locally.

import { Handler, Context } from "@netlify/functions";

const getOpenAIKey = () => {
  return Netlify.env.get("VITE_OPENAI_API_KEY");
};

const handler: Handler = async (event, context) => {
  console.log(getOpenAIKey());

  return {
    statusCode: 200,
    body: JSON.stringify({
      message: `foo function is working! :) ${getOpenAIKey()}`,
    }),
  };
};

export { handler };

Aha! Yes, that’s a “Lambda Compatibility Function”, aka the old way of authoring Netlify Functions. This doesn’t have access to Netlify.env in production. There’s some technical javascripty reasons for why we can’t make local dev behave exactly the same, so you’ll see Neltify.env be available locally, while it doesn’t in prod.

There’s two things you can do to work around this:

  1. Use process.env.VITE_OPENAI_API_KEY instead of Netlify.env.get("VITE_OPENAI_API_KEY")
    OR
  2. Migrate to using a Netlify Function 2.0. Here’s how that would look:
import { Context } from "@netlify/functions";

const getOpenAIKey = () => {
  return Netlify.env.get("VITE_OPENAI_API_KEY");
};

export default async (request: Request, context: Context) => {
   console.log(getOpenAIKey());

   return Response.json({
      message: `foo function is working! :) ${getOpenAIKey()}`
   })
}

Personally, I think Functions 2.0 are much more concise in how they’re written, and just a little more fun. If I were you, I’d opt to rewrite the Function - but you do you!