Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bindings.CanvasPatternInit is not a function (canvas > 2.8.0) #1934

Open
flohall opened this issue Nov 22, 2021 · 4 comments
Open

bindings.CanvasPatternInit is not a function (canvas > 2.8.0) #1934

flohall opened this issue Nov 22, 2021 · 4 comments

Comments

@flohall
Copy link

flohall commented Nov 22, 2021

Issue or Feature

We are developing a konva + node-canvas AWS Lambda serverless implementation. I am the only member in the team that switched some days ago to a new MacBook with Apple M1 Pro. Our application renders a video using konva + node-canvas and streams raw images to ffmpeg. The whole thing worked nicely inside the AWS Lambda docker container and locally on an Intel MacBook. On my new laptop I couldn't execute the code locally with canvas 2.8.0 - thats why I switched to github:Automattic/node-canvas#198080580a0e3938c48daae357b88a1638a9ddcd and now the code works on my new MacBook with Apple Silicon (M1 Pro) as well. See my answer on stack overflow here: https://stackoverflow.com/questions/67031187/error-node-canvas-was-built-without-jpeg-support/70064802#70064802
But with this version I cannot execute the code inside the docker anymore. So something between canvas 2.8.0 release and the current master breaks execution in Amazon Linux docker. The following issue occurs at runtime (no issues while building / installing canvas):

at Object.Module._extensions..js (internal/modules/cjs/loader.js:1101:10))  function aborted due to:  TypeError: bindings.CanvasPatternInit is not a function
2021-11-22T13:01:23.594Z        b68a7de0-7cae-47b5-a259-751150dba856    ERROR   Unhandled Promise Rejection     {"errorType":"Runtime.UnhandledPromiseRejection","errorMessage":"TypeError: bindings.CanvasPatternInit is not a function","reason":{"errorType":"TypeError","errorMessage":"bindings.CanvasPatternInit is not a function","stack":["TypeError: bindings.CanvasPatternInit is not a function","    at Object.<anonymous> (/var/task/node_modules/canvas/lib/pattern.js:12:10)","    at Module._compile (internal/modules/cjs/loader.js:1072:14)","    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1101:10)","    at Module.load (internal/modules/cjs/loader.js:937:32)","    at Function.Module._load (internal/modules/cjs/loader.js:778:12)","    at Module.require (internal/modules/cjs/loader.js:961:19)","    at require (internal/modules/cjs/helpers.js:92:18)","    at Object.<anonymous> (/var/task/node_modules/canvas/index.js:4:23)","    at Module._compile (internal/modules/cjs/loader.js:1072:14)","    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1101:10)"]},"promise":{},"stack":["Runtime.UnhandledPromiseRejection: TypeError: bindings.CanvasPatternInit is not a function","    at process.<anonymous> (/var/runtime/index.js:35:15)","    at process.emit (events.js:400:28)","    at processPromiseRejections (internal/process/promises.js:245:33)","    at processTicksAndRejections (internal/process/task_queues.js:96:32)"]}
time="2021-11-22T13:01:23.6" level=warning msg="State transition is not allowed"

Steps to Reproduce

not sure exactly what causes the issue, but here some canvas functions we use:


const stage = new Konva.Stage({
            width: stageWidth,
            height: stageHeight,
            container: canvas
        });
const layer = this.createLayer();
layer.listening(false);
stage.add(layer);

const image = new canvas.Image();
image.onload = () => {
                const konvaImage = new Konva.Image(imageProperties);
                konvaImage.cache();
                layer.add(konvaImage);
                resolve(konvaImage);
            };
            image.onerror = (err) => {
                reject(err);
            };
            image.src = imageUrl; 
});

stage.toCanvas().toBuffer('raw');

dockerfile:

### BUILDER CONTAINER IMAGE only used for building
FROM public.ecr.aws/lambda/nodejs:14 as builder

# update (and installing of software without fixed version) means that without code changes behaviour could be slightly different if a new image is created
# therefore every image version should be tested on staging system and deployed as is to production later
# this way we get most important OS security fixes
RUN yum -y update

# lambda insights extension to log lambda insights logs for better monitoring
RUN curl -O https://lambda-insights-extension.s3-ap-northeast-1.amazonaws.com/amazon_linux/lambda-insights-extension.rpm && \
    rpm -U lambda-insights-extension.rpm && \
    rm -f lambda-insights-extension.rpm

# only needed for setup (execution of subsequent command "tar")
RUN yum -y install tar xz

# old releases are used to have a fixed version of ffmpeg - update to most recent old-releases version if you like manually here
# TODO build ffmpeg from source or use yum installer for production ready code
RUN curl -o /tmp/ffmpeg.tar.xz https://www.johnvansickle.com/ffmpeg/old-releases/ffmpeg-4.2.2-amd64-static.tar.xz
RUN tar -xvf /tmp/ffmpeg.tar.xz -C /tmp/
RUN mkdir /opt/ffmpeglib/
RUN mv /tmp/ffmpeg-4.2.2-amd64-static/ffmpeg /opt/ffmpeglib/ffmpeg
RUN mv /tmp/ffmpeg-4.2.2-amd64-static/ffprobe /opt/ffmpeglib/ffprobe
RUN rm -r /tmp/*

# libraries needed for installation of npm package "canvas"
RUN yum -y install gcc-c++ cairo-devel pango-devel libjpeg-turbo-devel giflib-devel librsvg2-devel bzip2-devel

# needed for installing canvas diretly form github
RUN yum -y install git

# copy only files needed for npm install - so npm install will only be executed again if those files have changed
# .npmrc is needed for the vm-rendering-library to authenticate against nexus
COPY package.json .npmrc ./

# install all npm dependencies including dev dependencies
RUN npm install

# copy all remaining files not excluded in .dockerignore
COPY ./ ./

# fixing an issue in npm package canvas - must be executed after npm install, but before npm run build and again before execution
ENV LD_PRELOAD=/var/task/node_modules/canvas/build/Release/libz.so.1

# build typescript
RUN npm run build

# rename app.js to app.mjs to call ESM module from commonJS
RUN find ./dist -type f -name "*.js" -exec sed -i 's/\.js/\.mjs/g' {} \;
RUN find ./dist -type f -name "*.js" -exec sh -c 'mv "$0" "${0%.js}.mjs"' {} \;
RUN mv ./dist/video-merger/src/lambda/handler.mjs ./dist/video-merger/src/lambda/handler.js
RUN mv ./dist/video-renderer/src/lambda/handler.mjs ./dist/video-renderer/src/lambda/handler.js
RUN mv ./dist/video-splitter/src/lambda/handler.mjs ./dist/video-splitter/src/lambda/handler.js

# remove npm dev dependencies as they aren't needed anymore - make node_modules production ready
RUN npm prune --production

### END OF BUILDER CONTAINER IMAGE

### START OF RUNTIME CONTAINER IMAGE
FROM public.ecr.aws/lambda/nodejs:14

ARG SERVICE_NAME

# install again because some dependencies are needed at runtime
RUN yum -y install gcc-c++ cairo-devel pango-devel libjpeg-turbo-devel giflib-devel librsvg2-devel bzip2-devel
# copy over ffmepg from builder
COPY --from=builder /opt/ffmpeglib /opt/ffmpeglib
# copy over node_modules from builder
COPY --from=builder /var/task/node_modules ./node_modules
# copy shared files, which are shared between all different services
COPY --from=builder /var/task/dist/vm-rendering-backend-commons ./dist/vm-rendering-backend-commons
# copy over only the files from that specific service - rename the folder to service, as dynamic command names in docker are difficult
COPY --from=builder /var/task/dist/${SERVICE_NAME} ./dist/service

# fixing an issue in npm package canvas - must be executed after npm install, but before npm run build and again before execution
ENV LD_PRELOAD=/var/task/node_modules/canvas/build/Release/libz.so.1

ENV NODE_OPTIONS="--experimental-specifier-resolution=node"

# enable the lambda being executed - the correct handler function should be called
CMD ["dist/service/src/lambda/handler.handler"]

Your Environment

ENV 1 (on ARM MAC) (works)

  • Version of node-canvas: github:Automattic/node-canvas#198080580a0e3938c48daae357b88a1638a9ddcd
  • Version of konva: 8.2.3
  • module type: ESM
  • Environment: Apple M1 Pro / macOS Monterey / node.js 14

ENV 1 (on ARM MAC) (doesn't work)

ENV 2 (on AMD64 docker) (doesn't work):

  • Version of node-canvas: github:Automattic/node-canvas#198080580a0e3938c48daae357b88a1638a9ddcd
  • Version of konva: 8.2.3
  • module type: ESM
  • Environment: FROM public.ecr.aws/lambda/nodejs:14 / Apple M1 Pro / macOS Monterey
  • Issue: "function aborted due to: TypeError: bindings.CanvasPatternInit is not a function"

ENV 2 (on AMD64 docker) (works):

  • Version of node-canvas: 2.8.0
  • Version of konva: 8.2.3
  • module type: ESM
  • Environment: FROM public.ecr.aws/lambda/nodejs:14 / Apple M1 Pro / macOS Monterey
@flohall flohall changed the title bindings.CanvasPatternInit is not a function (canvas < 2.8.0) bindings.CanvasPatternInit is not a function (canvas > 2.8.0) Nov 22, 2021
@ppbl
Copy link

ppbl commented Dec 1, 2021

+1

First of all, thank the team for their efforts. I sincerely hope to release a version that supports Apple M1🙏

@ArthurClemens
Copy link

ArthurClemens commented Jan 25, 2022

I'm having the same issue with node-canvas 2.9.0 on a regular Macbook. Node v14.17.0.

@dev-sandeep
Copy link

Facing the same issue on Mac, Node 14

@NimishVerma
Copy link

having the same issue on a lambda layer

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants