Reputation: 3351
I'm creating a REST app that posts 2 images (base64 strings) for comparing using Resemble js. In my local, when I spin up the server and test using postman
, it works fine. I deployed the same code to Heroku
and test the heroku endpoint with the same data, it is throwing me an error.
Here is my code.
const express = require('express');
const app = express();
let port = process.env.PORT || 3000;
const bodyParser = require('body-parser');
const resemble = require("resemblejs");
app.use(bodyParser.json());
app.get('/', (req, res) => {
res.send('Hello World!!');
})
app.post('/', (req, res) => {
console.log(req.body);
var src = req.body.src;
var dest = req.body.dest;
resemble(src).compareTo(
dest
).ignoreColors().onComplete(data => {
console.log(JSON.stringify(data));
res.send(JSON.stringify(data));
}).catch(err => {
console.log(err);
});
})
app.listen(port, () => {
console.log(`Listening on port ${port}`);
})
You can test the api here.
The error I get when I looked at the heroku logs by using the command heroku logs --tail --app resemble-js-sf
2021-01-24T09:11:37.128025+00:00 heroku[web.1]: State changed from crashed to starting
2021-01-24T09:11:41.023786+00:00 heroku[web.1]: Starting process with command `node index.js`
2021-01-24T09:11:43.522499+00:00 app[web.1]: internal/modules/cjs/loader.js:1057
2021-01-24T09:11:43.522520+00:00 app[web.1]: return process.dlopen(module, path.toNamespacedPath(filename));
2021-01-24T09:11:43.522521+00:00 app[web.1]: ^
2021-01-24T09:11:43.522521+00:00 app[web.1]:
2021-01-24T09:11:43.522522+00:00 app[web.1]: Error: /app/node_modules/canvas/build/Release/canvas.node: invalid ELF header
2021-01-24T09:11:43.522522+00:00 app[web.1]: at Object.Module._extensions..node (internal/modules/cjs/loader.js:1057:18)
2021-01-24T09:11:43.522522+00:00 app[web.1]: at Module.load (internal/modules/cjs/loader.js:863:32)
2021-01-24T09:11:43.522523+00:00 app[web.1]: at Function.Module._load (internal/modules/cjs/loader.js:708:14)
2021-01-24T09:11:43.522523+00:00 app[web.1]: at Module.require (internal/modules/cjs/loader.js:887:19)
2021-01-24T09:11:43.522523+00:00 app[web.1]: at require (internal/modules/cjs/helpers.js:74:18)
2021-01-24T09:11:43.522524+00:00 app[web.1]: at Object.<anonymous> (/app/node_modules/canvas/lib/bindings.js:3:18)
2021-01-24T09:11:43.522524+00:00 app[web.1]: at Module._compile (internal/modules/cjs/loader.js:999:30)
2021-01-24T09:11:43.522524+00:00 app[web.1]: at Object.Module._extensions..js (internal/modules/cjs/loader.js:1027:10)
2021-01-24T09:11:43.522525+00:00 app[web.1]: at Module.load (internal/modules/cjs/loader.js:863:32)
2021-01-24T09:11:43.522525+00:00 app[web.1]: at Function.Module._load (internal/modules/cjs/loader.js:708:14)
2021-01-24T09:11:43.574021+00:00 heroku[web.1]: Process exited with status 1
2021-01-24T09:11:43.616109+00:00 heroku[web.1]: State changed from starting to crashed
2021-01-24T10:12:33.734281+00:00 heroku[web.1]: State changed from crashed to starting
2021-01-24T10:12:36.481044+00:00 heroku[web.1]: Starting process with command `node index.js`
2021-01-24T10:12:39.939626+00:00 app[web.1]: internal/modules/cjs/loader.js:1057
2021-01-24T10:12:39.939641+00:00 app[web.1]: return process.dlopen(module, path.toNamespacedPath(filename));
Please let me know where am I going wrong and how can I fix it?
Upvotes: 1
Views: 2902
Reputation: 108651
So, here's two things.
node_modules
.Don't commit node_modules
. If you have, remove it per @Chris's answer.
Your resemblejs
module depends on a module called canvas
. Canvas loads a bunch of native (not Javascript) code, called Cairo, to do its image-wrangling thing.
When you push your node app to heroku, it repeats the same npm install
operation that you can do locally, and loads all the modules mentioned in your package.json
and package-lock.json
. And, during that loading operation it compiles the native code as needed.
But, you've confounded the heroku process by checking in your node_modules
directory. (You've also put a whole mess of unnecessary stuff in your git repo, making it vastly larger than it needs to be.) It seems Heroku has decided it doesn't need to compile the Cairo code because it already shows up in your node_modules
directory. So, when you use your code, it tries to run the native code. And it discovers that the executable program is for the wrong operating system when it tries to run it. That's what Error: some/file/canvas.node: invalid ELF header
means. An ELF module is a Linux / FreeBSD / UNIX executable and linkable format object module. (I guess your development machine is not a Linux Ubuntu 18 machine like the ones they use in the heroku-18
stack.)
You must delete your node_modules subdirectory and commit that change.
canvas
is touchy about versions of nodejs. Mention this in your packages.json file and things should work on Heroku.
"engines": {
"node": "12.0.x"
},
Upvotes: 3
Reputation: 136958
The key error is here:
Error: /app/node_modules/canvas/build/Release/canvas.node: invalid ELF header
An ELF header is part of a binary file, e.g. a library compiled for a particular operating system and CPU architecture. If the ELF binary is not compatible for the system it's running on it won't work, and "invalid ELF header" is a good hint that this is what's happening here.
In this case you are getting this error because you have committed your node_modules/
folder. This contains your Node.js libraries, some of which must have been compiled against low-level libraries (as opposed to only depending on JavaScript code) that are not compatible with Heroku's infrastructure.
Untrack your node_modules/
directory, commit, and redeploy, e.g.:
git rm -r --cached node_modules
git commit -m "Remove node_modules from repository"
git push heroku master
This lets Heroku install your dependencies itself, making sure to get versions that are compatible.
Upvotes: 4