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.
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:
npm install
on LinuxPretty 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.
npm install --target_arch=x64 --target_platform=linux --target_libc=glibc
on MacThankfully 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.