serverless: Undefined variables being casted to the "undefined" string

This is a Bug Report

Description

  • What went wrong?

In the serverless.yml file I have defined some environment variables:

provider:
  name: aws
  runtime: nodejs6.10
  profile: jagi
  environment:
    STAGE: ${opt:stage}

In some cases ${opt:stage} may be undefined, for example on localhost when using serverless-offline. When it’s undefined it gets converted to the "undefined" string.

  • What did you expect should have happened?

I would expect it to be just undefined. It’s kinda weird to make comparisons like:

if (process.env.STAGE === 'undefined')

instead

if (process.env.STAGE === undefined)

Additional Data

  • Serverless Framework Version you’re using: 1.10.2
  • Operating System: MacOS 10.12.4

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Reactions: 3
  • Comments: 16 (15 by maintainers)

Most upvoted comments

Sounds great.

Just to recap, if you explicitly set a value to null in your serverless.yml then the framework won’t throw an error at build time. However, if you simply omit a value, causing the ${} variable to resolve to undefined, then the framework will throw an error - as opposed to just the warning that it currently logs today.

I think that gives strong feedback to users that something is wrong, but it also does allow enough flexibility to handle any edge cases where for some reason you do want to have a default null env var.

That seems reasonable. So, just throw an error at build time if an env var wasn’t set?

One concern that comes to mind though is that would make it impossible to deliberately omit an environment variable, no? And sometimes people do want to pass in an empty or null value to an environment variable, say if there’s a default that can optionally be overridden (e.g. use the hardcoded default in staging and override through an env var in prod, or, looking at it again, @jagi’s case on this issue, where ${opt:staging} isn’t set when running locally with serverless-offline).

Or, maybe I’m misunderstanding option 3?

Hi @pmuens thanks for the warm welcome!

As for your concern about language independence, I was thinking about two different ways to approach this:

  1. Just don’t add the key/value pair to the environment object/hash/dictionary if the input from serverless.yaml is undefined. So, from @jagi’s example, if ${opt:stage} evaluated to undefined then you simply wouldn’t put a "STAGE" key in the environment object. Doing so would mean that process.env.STAGE === undefined would be true. In Python: os.environ.get("STAGE") is None. And in Java: System.getenv().get("STAGE") == null. This makes it really clear that the env var was never set, but it’s less immediately clear where the problem is. New Serverless developers might not be sure whether they messed something up in the yaml file or if the problem was upstream in their local environment.

  2. Go ahead and set the key but make the value an empty string. Checking if an env var is ‘null or empty’ is pretty common across languages too. And I can see how that might be more expected as a developer using Serverless - you know at least something is working, since the key is getting from serverless.yaml into the env, but there clearly is a problem with the key, so you’d look at what was being templated into the yaml file. That said, people would have to check null-or-empty if they wanted to be safe before using an env var.

Overall I’m slightly more in favor of 1) just because it seems more straightforward. It’s a pretty natural thing to think that maybe empty / null / undefined values aren’t added to the environment. And it requires less work of developers who want to add checks around env vars - just check if it’s undefined/None/null.