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

Running multiple test files crashes when canvas is installed (Error: Module did not self-register: '.../canvas/build/Release/canvas.node'.) #740

Closed
6 tasks done
kleinfreund opened this issue Feb 12, 2022 · 22 comments · Fixed by #2772
Labels

Comments

@kleinfreund
Copy link
Contributor

kleinfreund commented Feb 12, 2022

Describe the bug

I’ve started exprimenting with Vitest and got all tests to pass individually; however, running npx vitest run . (or any set of test files together like npx vitest run src/*.test.js) crashes with the following error:

 RUN  /home/phil/dev/packages/vue-accessible-color-picker

node:internal/process/promises:265
            triggerUncaughtException(err, true /* fromPromise */);
            ^

Error: Module did not self-register: '/home/phil/dev/packages/vue-accessible-color-picker/node_modules/canvas/build/Release/canvas.node'.
    at Object.Module._extensions..node (node:internal/modules/cjs/loader:1185:18)
    at Module.load (node:internal/modules/cjs/loader:981:32)
    at Function.Module._load (node:internal/modules/cjs/loader:822:12)
    at Module.require (node:internal/modules/cjs/loader:1005:19)
    at require (node:internal/modules/cjs/helpers:102:18)
    at Object.<anonymous> (/home/phil/dev/packages/vue-accessible-color-picker/node_modules/canvas/lib/bindings.js:3:18)
    at Module._compile (node:internal/modules/cjs/loader:1103:14)
    at Object.Module._extensions..js (node:internal/modules/cjs/loader:1155:10)
    at Module.load (node:internal/modules/cjs/loader:981:32)
    at Function.Module._load (node:internal/modules/cjs/loader:822:12)

I’ve removed the node_modules directory contents several times, re-installed the dependencies, and the issue still happens. I’m writing this only because that’s the only tangible workaround I found for this problem.

Reproduction

git clone https://github.com/kleinfreund/vue-accessible-color-picker.git
cd vue-accessible-color-picker
npm install

npm test
# or
npx vitest run .

Expected behavior:

Test suite runs with all tests passing.

Actual behavior:

Vitest crashes and no tests are run.

Workaround: turn off threads

In #740 (comment), a workaround was presented. Turning off threads stops the issue from happening. Using the following configuration, the tests start working:

/// <reference types="vitest" />

import { defineConfig } from 'vite'
import Vue from '@vitejs/plugin-vue'

export default defineConfig({
  plugins: [
    Vue(),
  ],
  test: {
    threads: false,
    environment: 'jsdom',
  },
})

Notes

System Info

System:
    OS: Linux 5.13 Ubuntu 20.04.3 LTS (Focal Fossa)
    Container: Yes
    Shell: 5.8 - /usr/bin/zsh
  Binaries:
    Node: 16.14.0 - /usr/bin/node
    Yarn: 1.22.5 - ~/.yarn/bin/yarn
    npm: 8.5.0 - ~/dev/packages/vue-accessible-color-picker/node_modules/.bin/npm
  npmPackages:
    @vitejs/plugin-vue: ^2.2.0 => 2.2.0 
    vite: ^2.8.1 => 2.8.1 
    vitest: ^0.3.4 => 0.3.4

Used Package Manager

npm

Validations

@kleinfreund
Copy link
Contributor Author

This is caused by the package canvas being installed in my dependencies and used in my tests. JSDom automatically detects the package being present (see https://github.com/jsdom/jsdom#canvas-support) and allows me to test code that relies on document.createElement('canvas').getContext('2d').

Removing it allows me to run multiple tests at once (e.g npm test -- src/utilities/color-conversions/* works), but naturally, the tests relying on the canvas integration into JSDom fail now.

Interestingly, if ran individually, the tests relying on canvas work fine with Vitest (e.g. npm t -- src/ColorPicker.test.js passes). Just running them collectively results in the error reported originally.

@kleinfreund kleinfreund changed the title Running multiple test files crashes with Error: Module did not self-register Running multiple test files crashes when canvas is installed (Error: Module did not self-register: '.../canvas/build/Release/canvas.node'.) Feb 12, 2022
@bkuster
Copy link

bkuster commented Feb 15, 2022

We are having the same issue. Furthermore, once I get a single test to compile (and run), re-running the test will choke and cause a segmentation fault or (erratically) some nice native binding errors. OS and versions same as OP.

image

@kleinfreund
Copy link
Contributor Author

I have a feeling this might be caused by Automattic/node-canvas#1394.

@bkuster
Copy link

bkuster commented Feb 17, 2022

workaround: in your config set threads: false

chaii3 pushed a commit to chaii3/vitest that referenced this issue May 13, 2022
…ttledRefHistory` and `useDebouncedRefHistory` (vitest-dev#740)

Co-authored-by: Anthony Fu <[email protected]>
Co-authored-by: patak <[email protected]>
@molily
Copy link

molily commented Jun 1, 2022

Is there any way to use threads: true while mocking or disabling jsdom? Disabling threads means losing many of vitest's benefits.

Apparently, npm 7+ always installs canvas since it's a peer dependency of jsdom. So this code in jsdom require()s canvas even if it is not mentioned in my package.json dependencies.

I'm using vite-plugin-svelte and run into the "Module did not self-register" error if a test just includes a "Hello world" Svelte Component, without using the canvas API at all.

I‘ve tried vi.mock('canvas', () => ({}));. But this does not work, I guess because Vitest cannot mock what jsdom require()s. Any other ideas? Thanks.

@sheremet-va
Copy link
Member

sheremet-va commented Jun 1, 2022

Is there any way to use threads: true while mocking or disabling jsdom? Disabling threads means losing many of vitest's benefits.

What kind of benefits?

Apparently, npm 7+ always installs canvas since it's a peer dependency of jsdom. So this code in jsdom require()s canvas even if it is not mentioned in my package.json dependencies.

As a workaround, maybe there is an old version of this module that doesn't throw? And you can pin it in your package.json.

Also, you can try using happy-dom :)

@remorses
Copy link

This problem now happens even if you disable threads with threads: false

@dawiidio
Copy link

dawiidio commented Jun 19, 2022

threads: false makes things even worse. I'm using @testing-library/react and somehow setting threads: false breaks down all the screen usages while keeping threads: true breaks canvas 😅 so far the only solution I've found is this configuration:

{   
       //...
        minThreads: 0,
        maxThreads: 1,
}

in the above example canvas seems to be happy and all the tests run without any changes. Nevertheless in this configuration everything is extremely slow.

I also tried older versions of canvas, all with the same result.

UPDATE

As we can see here (thanks to @molily) and here jsdom only tries to include canvas if it was already installed directly as dependency in package.json, or indirectly by some other module. In my case the other module turned out to be ascii-art which installed canvas as it's dependency and jsdom included it automatically - welcome to the 2022 ¯\(ツ)

TEMPORARY SOLUTION

works only if you can uninstall library which included canvas for you. And of course it's only a messy workaround, not a real solution to the problem.

npm ls canvas # we want to see "-- (empty)" here

if you see anything other than "empty" try to identify which library included canvas as it's dependency and uninstall it with canvas:

npm uninstall --save canvas LIBRARY_NAME
rm -r node_modules/canvas # just to be sure ;)

then remove lock:

rm package-lock.json

and try again:

npm ls canvas # we want to see "-- (empty)"

@sheremet-va
Copy link
Member

threads: false makes things even worse

If you are running --no-threads, don't forget to call cleanup from @testing-library in your setupFile. Currently Vitest doesn't retain global hooks between tests, if --no-threads is called

@jsolly
Copy link

jsolly commented Sep 6, 2022

Just want to add that because I am also using setup files, having threads turned off has additional performance hits.

TIP
Note, that if you are running --no-threads, this setup file will be run in the same global scope multiple times. Meaning, that you are accessing the same global object before each test, so make sure you are not doing the same thing more than you need.

https://vitest.dev/config/#setupfiles

@MichaelFBA
Copy link

Seeing a similar issue with sharp

Error: 
Something went wrong installing the "sharp" module

Module did not self-register: '...../node_modules/sharp/build/Release/sharp-linux-x64.node'.

Possible solutions:
- Using worker threads? See https://sharp.pixelplumbing.com/install#worker-threads
- Install with verbose logging and look for errors: "npm install --ignore-scripts=false --foreground-scripts --verbose sharp"
- Install for the current linux-x64 runtime: "npm install --platform=linux --arch=x64 sharp"
- Consult the installation documentation: https://sharp.pixelplumbing.com/install

@sheremet-va
Copy link
Member

sheremet-va commented Sep 22, 2022

@MichaelFBA try calling require('sharp') in config file. Or in globalSetup. These are the only places user can call code outside of a worker thread.

@MichaelFBA
Copy link

@MichaelFBA try calling require('sharp') in config file. Or in globalSetup. These are the only places user can call code outside of a worker thread.

Yes I tried adding it to our global setup file for vitest. The issue seems to occur when running watch and only when you change a test does it break

@merkle-rking
Copy link

merkle-rking commented Jan 3, 2023

Since canvas is an optional peer dependency, we're considering a workaround to just not install peer dependencies locally and in our build agent. This only works for us because we don't have any other optional peer dependencies that we need to use locally or during testing. Though, if you did find yourself in that situation, you could list your optional peer dependencies as explicit dependencies.

npm ci --omit=optional

@ludufre
Copy link

ludufre commented Feb 22, 2023

@MichaelFBA try calling require('sharp') in config file. Or in globalSetup. These are the only places user can call code outside of a worker thread.

Yes I tried adding it to our global setup file for vitest. The issue seems to occur when running watch and only when you change a test does it break

Found any solution?

@ghsanti
Copy link

ghsanti commented Mar 24, 2023

I have had this error in the past with tensorflow and now with onnx runtime. Similar to canvas it seems to be because of a .node file @sheremet-va

Error: Module did not self-register: '../node_modules/onnxruntime-node/bin/napi-v3/linux/x64/onnxruntime_binding.node'.
 ❯ Object.<anonymous> ../node_modules/onnxruntime-node/lib/binding.ts:41:5

⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯
Serialized Error: {
  "code": "ERR_DLOPEN_FAILED",
}
⎯⎯⎯⎯⎯

wojtekmaj added a commit to wojtekmaj/react-pdf that referenced this issue Mar 31, 2023
@SebCorbin
Copy link

Had the same problem with pdfjs-dist including canvas as optional, npm i --no-optional did the work for me

@mw-sezzle
Copy link

I ran into this when I had the wrong path for include in my vite.config.ts file

@EdenTurgeman
Copy link

@SebCorbin Did you manage to find the issue? I'm also dealing with the same issue with pdfjs-dist

@CodySchaaf
Copy link

I tried all the suggestions, and while disabling threading worked it broke ci. The thing that finally worked for me was blowing away my node_modules deleting the package-lock and clearing the npm cache. Then finally reinstalling everything.

@kleinfreund
Copy link
Contributor Author

kleinfreund commented Jun 7, 2023

I'm also still having issues with this. This is not completely fixed.

  • jsdom:
    • threads: true ❌ "Error: Not implemented: HTMLCanvasElement.prototype.getContext (without installing the canvas npm package)" (note, canvas is installed)
    • threads: false
    • singleThread: true
  • happy-dom:
    • threads: true ❌ "TypeError: document.createElement(...).getContext is not a function"
    • threads: false ❌ "TypeError: document.createElement(...).getContext is not a function"
    • singleThread: true ❌ "TypeError: document.createElement(...).getContext is not a function"

@sheremet-va
Copy link
Member

I'm also still having issues with this. This is not completely fixed.

  • jsdom:

    • threads: true ❌ "Error: Not implemented: HTMLCanvasElement.prototype.getContext (without installing the canvas npm package)" (note, canvas is installed)
    • threads: false
    • singleThread: true
  • happy-dom:

    • threads: true ❌ "TypeError: document.createElement(...).getContext is not a function"
    • threads: false ❌ "TypeError: document.createElement(...).getContext is not a function"
    • singleThread: true ❌ "TypeError: document.createElement(...).getContext is not a function"

This is package's limitation, not Vitest. threads: true is not supported when using canvas package.

@github-actions github-actions bot locked and limited conversation to collaborators Jun 22, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.