Object spread in Lambda Function causes error when function is invoked

Hi,

When I try to use an Object spread operator inside a lambda function like this:

// tester.js
exports.handler = async function() {
  const obj = { a: 'a', c: 'c' };
  const obj2 = {
    b: 'b',
    ...obj,
  };

  return {
    statusCode: 200,
    body: JSON.stringify(obj2),
  };
};

After deploying it, when I try to invoke it thru /.netlify/functions/tester I end up with the following error:

{

  • errorType: “Runtime.ImportModuleError”,

  • errorMessage: “Error: Cannot find module ‘/opt/build/repo/node_modules/@babel/runtime/helpers/objectSpread2’ Require stack: - /var/task/src/src/functions/tester.js - /var/task/tester.js - /var/runtime/UserFunction.js - /var/runtime/index.js”,

  • trace: [

    • “Runtime.ImportModuleError: Error: Cannot find module ‘/opt/build/repo/node_modules/@babel/runtime/helpers/objectSpread2’”,

    • “Require stack:”,

    • “- /var/task/src/src/functions/tester.js”,

    • “- /var/task/tester.js”,

    • “- /var/runtime/UserFunction.js”,

    • “- /var/runtime/index.js”,

    • " at _loadUserApp (/var/runtime/UserFunction.js:100:13)",

    • " at Object.module.exports.load (/var/runtime/UserFunction.js:140:17)",

    • " at Object. (/var/runtime/index.js:43:30)",

    • " at Module._compile (internal/modules/cjs/loader.js:1015:30)",

    • " at Object.Module._extensions…js (internal/modules/cjs/loader.js:1035:10)",

    • " at Module.load (internal/modules/cjs/loader.js:879:32)",

    • " at Function.Module._load (internal/modules/cjs/loader.js:724:14)",

    • " at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:60:12)",

    • " at internal/main/run_main_module.js:17:47"]

}

Any idea how I can go around this issue while still be able to using the object spread operator?
Array spread operator seems fine tho, it’s just object spread operator than seems to be causing issues.

Update:
Rest syntax const { propA, ...rest } = obj; causes an error too

{

  • errorType: “Runtime.ImportModuleError”,

  • errorMessage: “Error: Cannot find module ‘/opt/build/repo/node_modules/@babel/runtime/helpers/objectWithoutProperties’ Require stack: - /var/task/src/src/functions/tester.js - /var/task/tester.js - /var/runtime/UserFunction.js - /var/runtime/index.js”,

  • trace: [

    • “Runtime.ImportModuleError: Error: Cannot find module ‘/opt/build/repo/node_modules/@babel/runtime/helpers/objectWithoutProperties’”,

    • “Require stack:”,

    • “- /var/task/src/src/functions/tester.js”,

    • “- /var/task/tester.js”,

    • “- /var/runtime/UserFunction.js”,

    • “- /var/runtime/index.js”,

    • " at _loadUserApp (/var/runtime/UserFunction.js:100:13)",

    • " at Object.module.exports.load (/var/runtime/UserFunction.js:140:17)",

    • " at Object. (/var/runtime/index.js:43:30)",

    • " at Module._compile (internal/modules/cjs/loader.js:1015:30)",

    • " at Object.Module._extensions…js (internal/modules/cjs/loader.js:1035:10)",

    • " at Module.load (internal/modules/cjs/loader.js:879:32)",

    • " at Function.Module._load (internal/modules/cjs/loader.js:724:14)",

    • " at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:60:12)",

    • " at internal/main/run_main_module.js:17:47"]

}

Hey there,
Can you please share your Netlify url so we can take a look?

In the meantime, maybe you’ll find something useful in this issue thread (Netlify functions are AWS lambdas “under the hood”):

Hey there Jen,

My previous reply disappeared, not sure if you got it but I’ll repost it.

Here are the links for my branch deploys where I’ve tried reproducing the issue

spread: https://5fe7391e448a6c0009e49581--kollab.netlify.app/api/actions/tester

rest: https://5fe764ca9a90e50007b2dde5--kollab.netlify.app/api/actions/tester

My main site https://kollab.netlify.app has had the use of spread + rest replaced by Object.assign but it makes the code much harder to read; being able to switch back to spread + rest is would be highly appreciated :slight_smile:

In the meantime I’ll be sure to check out the link you posted.

Thanks!

Edit: all of duplicated posts showed up after 1/2 hr so I deleted the earlier ones

Edit 2: after looking thru the link I’m not entirely sure how I can apply their fixes tho, they’re talking about configuring serverless framework which is a third party framework mainly for helping to deploy to AWS.
Is Netlify using serverless framework to deploy to AWS as well where I can throw in some config files as mentioned in the github issue to adjust how the lambda functions are built + deployed?

Hey @collabiersid,
Sorry to be not very clear with that link! What I was hoping it would show is that AWS lambdas use a version of Node that supports the spread operator and rest syntax by default… so I think what people are discussing in that thread is how to remove/update babel accordingly.

When I take the tester.js function at the top of this thread, add a rest syntax example to it and deploy, it seems to show the right thing for me, with no error: https://vigilant-bell-b96f12.netlify.app/.netlify/functions/test-es6

// tester-2.js
exports.handler = async function() {
  // rest
  function sum(x, y, z) {
    return x + y + z;
  }
  const numbers = [1, 2, 3];
  console.log(sum(...numbers));
  
  // spread
  const obj = { a: 'a', c: 'c' };
  const obj2 = {
    b: 'b',
    ...obj,
  };
  return {
    statusCode: 200,
    body: JSON.stringify(obj2),
  };
};

shows 6 in the function logs and this in the browser:

{"b":"b","a":"a","c":"c"}

so I think the error you’re running into may have to do with your dependencies.

Hey @jen,

Ah yea I get what you mean now, and yea the node I’ve specified as the environment (v12) supports spread and rest by default.

Your example looks correct, so you’re right in the sense that somehow I’ve modified the build process in some ways I’m unaware of. But what would affect the build process for functions tho?

The tester function I deployed had 0 dependencies (just that particular function, not the whole project), and it seems the culprit is Babel trying to transform the code even tho it’s not necessary and then failing at it.
Do you know how I might’ve caused babel to be used to transform the function code, or how I can disable transformation in netlify’s build process?

Hi @jen

Any idea how I can stop the babel transformation of my functions?

Hey @collabiersid,
I know you said that Babel is not a direct dependency of your function- are you using it in your root package.json? If so, then it will interfere with your function code.

Something you could try would be zipping the function so it doesn’t get any of your projects’ other dependencies. You could do that as part of your build command, kind of like what’s shown here:

So the scripts section of your package.json would be:

...
   "build": "npm run build:zipped; npm run whatever-other-command"
   "build:zipped": "zip -r your-functions-dir.zip your-functions-dir"
...

Let us know if that helps.

Hi @jen

Thanks very much for the code reference, I’ll give it a try.

Btw, do you happen to know what netlify’s default build process for functions is like? A reference to the code (if it’s open-sourced) would be great!
I was assuming it would be this: https://github.com/netlify/build/blob/88852c4a584a60170084b69dcf21c878867cc6e8/packages/functions-utils/src/main.js which eventually uses this package https://github.com/netlify/zip-it-and-ship-it to zip the functions and their dependencies up.
However, nowhere within them do I see babel being used so I’m rather confused.

Thanks again for you help!

An update here in case others face a similar problem

So what happened in my case was:

  1. I have the netlify-plugin-inline-functions-env plugin installed, and this plugin uses babel to do its transformation before lambda functions are packaged.
    • without plugins they’d just be bundled by zip-it-and-ship-it
  2. I also have a babel.config.json in the project root which uses Quasar framework’s babel preset and transforms the code for browser environment.
  3. The above interferes with the netlify-plugin-inline-functions-env transformation process which causes my lambda functions to be transpiled for browsers instead.
  4. To ensure that lambda functions are NOT transpiled for browser environment, I created another .babelrc babel config within the functions folder, so this config file will take override any overlapping config rules i.e. target environment set to { "node": "current" } within ./functions/.babelrc

I still do not fully understand why spread and rest would be broken when transpiled for browser, I’m guessing it might be due to the way quasar references the babel runtime package within its preset https://github.com/quasarframework/quasar/blob/24f584d9df22aa07ae4d8ab74ca194b6dd36d7ea/babel-preset-app/index.js#L24

Lastly, thanks Jen for trying to troubleshoot this for me and also pointing me in the right direction, it’s not easy given that (I now realize) not all relevant information has been presented.