vercel: node-canvas runtime error

Hi 👋 , I’m having a runtime error with my app that uses node-canvas@2.6.0. It doesn’t uses it directly, but through the package text2png@2.3.0. Here is the error I got

2019-12-23T05:47:22.676Z	undefined	ERROR	Error: libuuid.so.1: cannot open shared object file: No such file or directory
    at Object.Module._extensions..node (internal/modules/cjs/loader.js:807:18)
    at Module.load (internal/modules/cjs/loader.js:653:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:593:12)
    at Function.Module._load (internal/modules/cjs/loader.js:585:3)
    at Module.require (internal/modules/cjs/loader.js:692:17)
    at require (internal/modules/cjs/helpers.js:25:18)
    at Object.<anonymous> (/var/task/node_modules/canvas/lib/bindings.js:3:18)
    at Module._compile (internal/modules/cjs/loader.js:778:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:789:10)
    at Module.load (internal/modules/cjs/loader.js:653:32)

As far I know, right now AWS Lambda functions doesn’t include the necessary libraries to work correctly with this package. This is describe in node-canvas#1448 and now I’m wondering if there is a work around in now to this issue.

About this issue

  • Original URL
  • State: open
  • Created 5 years ago
  • Reactions: 3
  • Comments: 56 (4 by maintainers)

Commits related to this issue

Most upvoted comments

As an alternative to node-canvas, try @napi-rs/canvas which has a lot of the same features.

Thanks to @Brooooooklyn

Right you are @likeablob , thanks a lot!

2 noteworthy things:

  1. yum install libuuid-devel libmount-devel && cp /lib64/{libuuid,libmount,libblkid}.so.1 node_modules/canvas/build/Release/ worked while the cp canvas_lib64/*so.1 node_modules/canvas/build/Release/ method (having downloaded and unzipped the files) did not work (for me).
  2. What @likeablob said was also a problem so I had to call npm run build from within my now-build npm script.

If it helps anyone, I ended up with this in my package.json:

  "scripts": {
    "test": "jest",
    "dev": "next dev",
    "build": "next build",
    "now-build": "yum install libuuid-devel libmount-devel && cp /lib64/{libuuid,libmount,libblkid}.so.1 node_modules/canvas/build/Release/ && npm run build",
    "start": "next start",
    "deploy": "now"
  },

As an ugly workaround, I ended up using the following now-build.

$ wget https://github.com/jwerre/node-canvas-lambda/raw/master/canvas-lib64-layer.zip
$ unzip -j -d canvas_lib64 canvas-lib64-layer.zip
{
  "scripts": {
    "now-build": "cp canvas_lib64/*so.1 node_modules/canvas/build/Release/"
  }
}

BTW, Thanks @jwerre !

Checkout the demo of @napi-rs/canvas on Vercel, without any configuration: https://github.com/Brooooooklyn/vercel-canvas/blob/main/api/canvas.js

https://vercel.skia.rs/api/canvas

I’ve solved this issue in a bit more complicated way:

  • added two commands to `package.json
"install-bin": "./scripts/install.sh",
"postinstall": "patch-package && (yarn run install-bin)"
  • where install.sh is checking that target system is correct to run the command
#!/bin/bash
if ! [ -x "$(command -v yum)" ]; then
  echo 'not a target system'
  exit 0;
fi

yum install libuuid-devel libmount-devel && cp /lib64/{libuuid,libmount,libblkid}.so.1 node_modules/canvas/build/Release/

I get this after everything:

ERROR Error: /lib64/libz.so.1: version `ZLIB_1.2.9’ not found (required by /var/task/node_modules/canvas/build/Release/libpng16.so.16)

I have a working config. I hope the explanations will help. Don’t hesitate to ask for precision on stuff I’ve may have forgot to share 😃

My setup include:

  • at least those npm scripts:
  "scripts": {
    "build": "next build",
    "vercel-build": "yum install libuuid-devel libmount-devel zlib && cp /lib64/{libuuid,libmount,libblkid,libz}.so.1 node_modules/canvas/build/Release/ && npm run build",
  },
  • node-canvas ^2.6.1 (don’t work on the last version for me)
  • last version of Next.js
  • the node default version on Vercel (14.x, no need to stay on 12.x) and:
  • no setup.sh
  • no LD_LIBRARY_PATH / LD_PRELOAD env variables

My use case was to create a social card for Open Graph, so i have a /api/social-image.png.js file with this as default function:

export default async (req, res) => {
	const image = await createImage()
	res.writeHead(200, {
		"Content-Type": "image/png",
		"Content-Length": Buffer.byteLength(image),
	})
	res.end(image);
}

createImage being the function who calls node-canvas

I tried a number of possible combinations of solutions suggested between three different threads. This is the only one that has worked for me. Thank you @TixieBorg

switched to node 12 runtime and it just started working \o/ Still have the weird yum install hack in my package.json, though, looks like:

  "scripts": {
    "vercel-build": "yum install libuuid-devel libmount-devel zlib && cp /lib64/{libuuid,libmount,libblkid,libz}.so.1 node_modules/canvas/build/Release/"
  }

currently using "vercel-build": "yum install libuuid-devel libmount-devel && cp /lib64/{libuuid,libmount,libblkid}.so.1 node_modules/canvas/build/Release/ && next build" in my package.json

and yarn install && yarn run vercel-build in my vercel install script

But this only works with Node 16, and does not work with Node 18

Any idea how to get it to work with Node 18?

Switched to just rendering on the frontend and using urlbox.io 😃

On Tue, Dec 14, 2021 at 3:47 PM Steven @.***> wrote:

As an alternative to node-canvas, try @napi-rs/canvas @.***/canvas> which has a lot of the same features

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/vercel/vercel/issues/3460#issuecomment-994061204, or unsubscribe https://github.com/notifications/unsubscribe-auth/AC4Q26NZNK3CCYJJD2T45PLUQ63NPANCNFSM4J6QFO4A .

@rzinurov still get the same error using canvas@2.6.1

The easiest way out that I’ve found was to downgrade to canvas@2.6.1. This version of node-canvas does not require newer versions of libuuid-devel, libmount-devel and zlib, and it works in Vercel Node14 runtime without any extra dependencies. In case if you need to use node-canvas 2.7.0+, you’d most likely have to build zlib-1.2.9 from sources and copy libs from /lib64/ to node_modules/canvas/build/Release/ in the vercel-build script, as it was suggested above, well at least until zlib-1.2.9 becomes available through yum.

@elmariachi111 Wow thanks so much, spent 2 days on this error, downgrading to node 12.x was the only working solution… Would love if someone finds a way to fix it on Node 14 too…

I found a solution through this issue: https://github.com/Automattic/node-canvas/issues/1779#issuecomment-896125623.

Adding this to top of your next.config.js and deploy should work!

if (
  process.env.LD_LIBRARY_PATH == null ||
  !process.env.LD_LIBRARY_PATH.includes(
    `${process.env.PWD}/node_modules/canvas/build/Release:`,
  )
) {
  process.env.LD_LIBRARY_PATH = `${
    process.env.PWD
  }/node_modules/canvas/build/Release:${process.env.LD_LIBRARY_PATH || ''}`;
}

Actually this solution only works in client rendering, if you’re trying to use SSR this solution won’t work for you.

I have a working config. I hope the explanations will help. Don’t hesitate to ask for precision on stuff I’ve may have forgot to share 😃

My setup include:

  • at least those npm scripts:
  "scripts": {
    "build": "next build",
    "vercel-build": "yum install libuuid-devel libmount-devel zlib && cp /lib64/{libuuid,libmount,libblkid,libz}.so.1 node_modules/canvas/build/Release/ && npm run build",
  },
  • node-canvas ^2.6.1 (don’t work on the last version for me)
  • last version of Next.js
  • the node default version on Vercel (14.x, no need to stay on 12.x) and:
  • no setup.sh
  • no LD_LIBRARY_PATH / LD_PRELOAD env variables

My use case was to create a social card for Open Graph, so i have a /api/social-image.png.js file with this as default function:

export default async (req, res) => {
	const image = await createImage()
	res.writeHead(200, {
		"Content-Type": "image/png",
		"Content-Length": Buffer.byteLength(image),
	})
	res.end(image);
}

createImage being the function who calls node-canvas

Just fought this for the better part of 4 hours. There seems to be a lot of advice across a few different GitHub issues, none of which worked for me on their own. First missing libraries(libuuid), then a wrong/missing version of zlib (ZLIB_1.2.9 not found (required by /opt/nodejs/node_modules/canvas/build/Release/libpng16.so.16)).

Here’s what finally ended up working for me:

Node: 14.x canvas: ^2.8.0

  1. Add a setup.sh file to the project :
wget https://zlib.net/fossils/zlib-1.2.9.tar.gz
tar -xf zlib-1.2.9.tar.gz
cd zlib-1.2.9
sh configure
make
ls -l libz*
cp libz.so.1 ../node_modules/canvas/build/Release/
  1. Update package.json with a vercel-build script to handle installing the missing packages:
"vercel-build": "yum install libuuid-devel libmount-devel wget && cp /lib64/{libuuid,libmount,libblkid}.so.1 node_modules/canvas/build/Release/ && ./setup.sh && npm run build"

Things that didn’t work for me

  1. Just using the vercel-build command, including zlib
  2. Setting the LD_LIBRARY_PATH or LD_PRELOAD environment variables

@shawninder this works for me:

import { loadImage, createCanvas, registerFont } from 'canvas';
import path from 'path';

registerFont(path.resolve('./public/CircularPro-Book.otf'), { family: 'CircularPro' });

I’ve solved this issue in a bit more complicated way:

  • added two commands to `package.json
"install-bin": "./scripts/install.sh",
"postinstall": "patch-package && (yarn run install-bin)"
  • where install.sh is checking that target system is correct to run the command
#!/bin/bash
if ! [ -x "$(command -v yum)" ]; then
  echo 'not a target system'
  exit 0;
fi

yum install libuuid-devel libmount-devel && cp /lib64/{libuuid,libmount,libblkid}.so.1 node_modules/canvas/build/Release/

I ended up having to manually generate my libz.so.1 file from zlib-1.2.9, because yum would only install v1.2.7+(some amazon suffix) from vercel-build. I also went ahead and manually added all the other *.so files that canvas needs (ie libblkid.so.1, etc.) in a arbitrary root folder. Then I run vercel-build to copy the files from that root folder into build/Release.

So mine ended up looking like this:

"vercel-build": "cp canvas_lib64/* node_modules/canvas/build/Release/ && npm run build"

and the files I added to canvas_lib64 were:

libblkid.so.1
libfontconfig.so.1
libmount.so.1
libpixman-1.so.0
libpng16.so.16
libuuid.so.1
libz.so.1 (manually renamed this after explicity importing libz.so.1.2.9)

That seems to have solved it for me.

@chrisco255 When I try this I get cp: cannot stat ‘canvas_lib64/*’: No such file or directory

I ended up having to manually generate my libz.so.1 file from zlib-1.2.9, because yum would only install v1.2.7+(some amazon suffix) from vercel-build. I also went ahead and manually added all the other *.so files that canvas needs (ie libblkid.so.1, etc.) in a arbitrary root folder. Then I run vercel-build to copy the files from that root folder into build/Release.

So mine ended up looking like this:

"vercel-build": "cp canvas_lib64/* node_modules/canvas/build/Release/ && npm run build"

and the files I added to canvas_lib64 were:

libblkid.so.1
libfontconfig.so.1
libmount.so.1
libpixman-1.so.0
libpng16.so.16
libuuid.so.1
libz.so.1 (manually renamed this after explicity importing libz.so.1.2.9)

That seems to have solved it for me.

Added --skip-broken to the yum command to make it work, but really… Sounds weird

some of the dependencies is now broken,

Error: Package: glibc-2.26-48.amzn2.i686 (amzn2-core)

Thank you so much @mschonvogel it worked!

I guess it was the path.resolve that I needed. Perhaps when I had tried it earlier something else was wrong?

Sorry for highjacking the thread everyone, but this really did help!

@shawninder you’re the MVP – you helped me figure this out

Glad I could help 😃

Unfortunately, this wasn’t the end of my problems with node-canvas in the context of a Vercel deployment. Now that things are building, I’m finding I can’t load any fonts… Perhaps someone here would be able to give me a hand via this stackoverflow post: https://stackoverflow.com/questions/60103921/node-canvas-registerfont-cant-find-font-file-once-deployed-works-locally