2

I am running to an error that says "Invalid ELF header" for a package called "argon2". When uploading my code to AWS Lambda through the serverless framework. The code runs perfectly when running locally.

Development on MacOS Big Sur version 11.4

Image of the error I am getting

I've researched a little bit on the error and people are saying to use Docker to compile the packages and then send to Lambda. I haven't worked with Docker much and wanted to explore other options before attempting the docker solution.

Any guidance or help would be much appreciated! I've been stuck on this bug for over a day or two.

John Rotenstein
  • 241,921
  • 22
  • 380
  • 470
Michael Remy
  • 23
  • 1
  • 4

3 Answers3

9

What is going on?

The package you are using (argon2) contains bindings to a C implementation of the argon2 algorithm. In other words, the package itself wraps a library written in C, and makes it accessible inside your node.js environment.

That C package is also shipped with your package, and compiled (or downloaded) when you run npm install argon2. That means that after installing argon2, there is a binary shared library on your file system, that is interfacing with your node environment. Because you are installing on MacOS, the binary will be compiled (or downloaded) for Mac. This means you end up with a MACH-O file (which is the format executables for macOS come in) instead of an ELF file (which is format Linux uses for executables).

Now your Lambda (which runs Linux under the hood) effectively complains, that the executable you've built on your Mac is not a Linux executable.

How do you fix this?

In simple terms, you need a way to npm install that will build or download the argon2 version for Linux. There are two different ways to achieve this. Pick one:

  1. npm install on Linux

Pretty much as the title says, download and build your dependencies under Linux. You can use a Virtual Machine, or a Docker container to do that. Another option would be to use the AWS build SaaS product (AWS CodeBuild) to do this.

  1. npm install --target_arch=x64 --target_platform=linux --target_libc=glibc on Mac

Thankfully argon2 comes with support for node-pre-gyp. They effectively provide you with prebuild binaries, which means that you can just pull the linux binaries end do not have to compile them yourself. To do that, thow away your node_modules folder and run npm install --target_arch=x64 --target_platform=linux. This will download the Linux files, instead of the macOs files. You can then push everything into your lambda. Please note that this means your application will not run locally anymore, since your mac cannot run the Linux executable (you would have to npm install again, leaving out the two parameters to get back to the MacOS version).

Please note that there might be packages apart from argon2 that do not support MacOS, in which case you would have to take the first option.

Daniel Klischies
  • 1,095
  • 7
  • 14
  • 1
    Thank you for such a detailed response and taking the time to explain what is happening. I attempted #2 and got an error. > node-pre-gyp install --fallback-to-build node-pre-gyp ERR! install response status 404 Not Found on https://github.com/ranisalt/node-argon2/releases/download/v0.28.2/argon2-v0.28.2-napi-v3-linux-x64-unknown.tar.gz node-pre-gyp WARN Pre-built binaries not installable for argon2@0.28.2 and node@12.0.0 (node-v72 ABI, unknown) (falling back to source compile with node-gyp) I am using NVM and I've tried node 14 and 12. – Michael Remy Sep 24 '21 at 19:39
  • Oops, try `npm install --target_arch=x64 --target_platform=linux --target_libc=glibc`. The error message tells you that it cant find the binary at that location. if you look at the releases page at https://github.com/ranisalt/node-argon2/releases you can see that there are glibc and musl versions for linux x64, and you need to select one, which that command should do. – Daniel Klischies Sep 24 '21 at 19:57
  • 1
    Thanks for you help. I ended up just switching to Bcryptjs instead of using Argon2 and that ended up resolving my error. – Michael Remy Sep 27 '21 at 18:33
1

Just to add. To deploy to Lambda you would (eventually) need to send your files in a zip. And to bundle your project efficiently you would need a bundler like Webpack. The problem is, argon2 and any other hash implementations like bcrypt use node-pre-gyp dependency that doesn't work well with bundler. So the options are:

  • Just zip the entire project and everything inside node_modules. This means including everything that isn't used which can be massive.
  • When using Webpack exclude argon2 from the config with the consequence that it has to be manually installed in target environment.
  • Use a pure js version of argon2 which is much slower.
  • If you use it to manage passwords then you can drop it for a cloud service like AWS KMS that offers secure symmetric keys. However these keys encrypt, not hash so for the better or worse you can decrypt the passwords back to plain text.

Remember that hashing performance itself is proportional to memory and CPU. So running a hashing algorithm for fast result could mean high Lambda bill.

inmyth
  • 8,880
  • 4
  • 47
  • 52
0

Cause I changed my Operation system and the project before the node modules installed in windows, I just delete the node_modules folder and run npm install again

Tyler2P
  • 2,324
  • 26
  • 22
  • 31