Skip to content

Prisma crashes with promise rejections (among others in Vitest) #18577

@nakleiderer

Description

@nakleiderer

NOTE: I'm cross-posting this issue from vitest-dev/vitest#3106 because it's unclear which tool is causing the issue, the bug might require collaboration between vitest and prisma, and for other members of the vitest or prisma communities to be able to search this issue in their respective repositories.

Bug description

When running tests with Vitest and Prisma, I receive a variety of crashes: segmentation fault, bus error, and abort. Sometimes, Rust is able to print a stack trace before crashing:

Super long debug output and stack trace
❯ npm run test -- --run

> vitest-crash-reproduction@0.0.0 test
> vitest --run

  vite:config bundled config file loaded in 24.26ms +0ms
  vite:esbuild init tsconfck (root: /vitest-crash-reproduction) +0ms
  vite:esbuild init tsconfck (root: /vitest-crash-reproduction) +0ms
  vite:esbuild init tsconfck end +1ms
  vite:esbuild init tsconfck end +0ms
  vite:config using resolved config: {
  vite:config   test: {},
  vite:config   logLevel: 'error',
  vite:config   configFile: '/vitest-crash-reproduction/vite.config.ts',
  vite:config   mode: 'test',
  vite:config   plugins: [
  vite:config     'vite:pre-alias',
  vite:config     'alias',
  vite:config     'vitest',
  vite:config     'vitest:env-replacer',
  vite:config     'vitest:global-setup-plugin',
  vite:config     'vitest:css-disable',
  vite:config     'vite:modulepreload-polyfill',
  vite:config     'vite:resolve',
  vite:config     'vite:html-inline-proxy',
  vite:config     'vite:css',
  vite:config     'vite:esbuild',
  vite:config     'vite:json',
  vite:config     'vite:wasm-helper',
  vite:config     'vite:worker',
  vite:config     'vite:asset',
  vite:config     'vitest:coverage-transform',
  vite:config     'vite:wasm-fallback',
  vite:config     'vite:define',
  vite:config     'vite:css-post',
  vite:config     'vite:worker-import-meta-url',
  vite:config     'vite:asset-import-meta-url',
  vite:config     'vite:dynamic-import-vars',
  vite:config     'vite:import-glob',
  vite:config     'vitest:css-empty-post',
  vite:config     'vite:client-inject',
  vite:config     'vite:import-analysis'
  vite:config   ],
  vite:config   esbuild: { sourcemap: 'external', legalComments: 'inline' },
  vite:config   resolve: {
  vite:config     mainFields: [],
  vite:config     browserField: false,
  vite:config     conditions: [ 'node' ],
  vite:config     extensions: [
  vite:config       '.mjs',  '.js',
  vite:config       '.mts',  '.ts',
  vite:config       '.jsx',  '.tsx',
  vite:config       '.json'
  vite:config     ],
  vite:config     dedupe: [],
  vite:config     preserveSymlinks: false,
  vite:config     alias: [ [Object], [Object] ]
  vite:config   },
  vite:config   server: {
  vite:config     preTransformRequests: false,
  vite:config     watch: { persistent: false, depth: 0, ignored: [Array] },
  vite:config     open: undefined,
  vite:config     hmr: false,
  vite:config     middlewareMode: false,
  vite:config     fs: { strict: true, allow: [Array], deny: [Array] }
  vite:config   },
  vite:config   css: { modules: { generateScopedName: [Function (anonymous)] } },
  vite:config   optimizeDeps: {
  vite:config     disabled: true,
  vite:config     entries: [],
  vite:config     esbuildOptions: { preserveSymlinks: false }
  vite:config   },
  vite:config   configFileDependencies: [
  vite:config     '/vitest-crash-reproduction/vite.config.ts'
  vite:config   ],
  vite:config   inlineConfig: {
  vite:config     logLevel: 'error',
  vite:config     configFile: '/vitest-crash-reproduction/vite.config.ts',
  vite:config     mode: 'test',
  vite:config     plugins: [ [Object], [Object], [Object], [Object], [Object], [Object] ]
  vite:config   },
  vite:config   root: '/vitest-crash-reproduction',
  vite:config   base: '/',
  vite:config   publicDir: '/vitest-crash-reproduction/public',
  vite:config   cacheDir: '/vitest-crash-reproduction/node_modules/.vite',
  vite:config   command: 'serve',
  vite:config   ssr: {
  vite:config     format: 'esm',
  vite:config     target: 'node',
  vite:config     optimizeDeps: { disabled: true, esbuildOptions: [Object] }
  vite:config   },
  vite:config   isWorker: false,
  vite:config   mainConfig: null,
  vite:config   isProduction: false,
  vite:config   build: {
  vite:config     target: [ 'es2020', 'edge88', 'firefox78', 'chrome87', 'safari13' ],
  vite:config     cssTarget: [ 'es2020', 'edge88', 'firefox78', 'chrome87', 'safari13' ],
  vite:config     outDir: 'dist',
  vite:config     assetsDir: 'assets',
  vite:config     assetsInlineLimit: 4096,
  vite:config     cssCodeSplit: true,
  vite:config     sourcemap: false,
  vite:config     rollupOptions: {},
  vite:config     minify: 'esbuild',
  vite:config     terserOptions: {},
  vite:config     write: true,
  vite:config     emptyOutDir: null,
  vite:config     copyPublicDir: true,
  vite:config     manifest: false,
  vite:config     lib: false,
  vite:config     ssr: false,
  vite:config     ssrManifest: false,
  vite:config     reportCompressedSize: true,
  vite:config     chunkSizeWarningLimit: 500,
  vite:config     watch: null,
  vite:config     commonjsOptions: { include: [Array], extensions: [Array] },
  vite:config     dynamicImportVarsOptions: { warnOnError: true, exclude: [Array] },
  vite:config     modulePreload: { polyfill: true }
  vite:config   },
  vite:config   preview: {
  vite:config     port: undefined,
  vite:config     strictPort: undefined,
  vite:config     host: undefined,
  vite:config     https: undefined,
  vite:config     open: undefined,
  vite:config     proxy: undefined,
  vite:config     cors: undefined,
  vite:config     headers: undefined
  vite:config   },
  vite:config   env: { BASE_URL: '/', MODE: 'test', DEV: true, PROD: false },
  vite:config   assetsInclude: [Function: assetsInclude],
  vite:config   logger: {
  vite:config     hasWarned: false,
  vite:config     info: [Function: info],
  vite:config     warn: [Function: warn],
  vite:config     warnOnce: [Function: warnOnce],
  vite:config     error: [Function: error],
  vite:config     clearScreen: [Function: clearScreen],
  vite:config     hasErrorLogged: [Function: hasErrorLogged]
  vite:config   },
  vite:config   packageCache: Map(0) {},
  vite:config   createResolver: [Function: createResolver],
  vite:config   worker: {
  vite:config     format: 'iife',
  vite:config     plugins: [
  vite:config       'vite:pre-alias',
  vite:config       'alias',
  vite:config       'vite:modulepreload-polyfill',
  vite:config       'vite:resolve',
  vite:config       'vite:html-inline-proxy',
  vite:config       'vite:css',
  vite:config       'vite:esbuild',
  vite:config       'vite:json',
  vite:config       'vite:wasm-helper',
  vite:config       'vite:worker',
  vite:config       'vite:asset',
  vite:config       'vite:wasm-fallback',
  vite:config       'vite:define',
  vite:config       'vite:css-post',
  vite:config       'vite:worker-import-meta-url',
  vite:config       'vite:asset-import-meta-url',
  vite:config       'vite:dynamic-import-vars',
  vite:config       'vite:import-glob',
  vite:config       'vite:client-inject',
  vite:config       'vite:import-analysis'
  vite:config     ],
  vite:config     rollupOptions: {},
  vite:config     getSortedPlugins: [Function: getSortedPlugins],
  vite:config     getSortedPluginHooks: [Function: getSortedPluginHooks]
  vite:config   },
  vite:config   appType: 'spa',
  vite:config   experimental: { importGlobRestoreExtension: false, hmrPartialAccept: false },
  vite:config   getSortedPlugins: [Function: getSortedPlugins],
  vite:config   getSortedPluginHooks: [Function: getSortedPluginHooks]
  vite:config } +4ms
  connect:dispatcher use / viteTimeMiddleware +0ms
  connect:dispatcher use / corsMiddleware +0ms
  connect:dispatcher use /__open-in-editor launchEditorMiddleware +0ms
  connect:dispatcher use / viteServePublicMiddleware +0ms
  connect:dispatcher use / viteTransformMiddleware +0ms
  connect:dispatcher use / viteServeRawFsMiddleware +0ms
  connect:dispatcher use / viteServeStaticMiddleware +0ms
  connect:dispatcher use / viteHtmlFallbackMiddleware +0ms
  connect:dispatcher use / viteIndexHtmlMiddleware +0ms
  connect:dispatcher use / vite404Middleware +0ms
  connect:dispatcher use / viteErrorMiddleware +0ms

 RUN  v0.29.8 /vitest-crash-reproduction

  vite-node:server:request /@vite/env +0ms
  vite:resolve 0.86ms /@vite/env -> /vitest-crash-reproduction/node_modules/vite/dist/client/env.mjs +0ms
  vite:load 0.66ms [fs] /@vite/env +0ms
  vite:import-analysis 0.15ms [no imports] node_modules/vite/dist/client/env.mjs +0ms
  vite:transform 4.21ms /@vite/env +0ms
  vite:resolve 0.78ms vitest -> /vitest-crash-reproduction/node_modules/vitest/dist/index.js +15ms
2023-03-30T14:59:19.722Z vite-node:client:execute /@vite/env
2023-03-30T14:59:19.755Z vite-node:client:native /vitest-crash-reproduction/node_modules/vitest/dist/runners.js
  vite-node:server:request /vitest-crash-reproduction/test/reproduction.test.ts +54ms
  vite:load 0.27ms [fs] test/reproduction.test.ts +51ms
  vite:import-analysis 1.30ms [0 imports rewritten] test/reproduction.test.ts +51ms
  vite:transform 3.50ms test/reproduction.test.ts +50ms
2023-03-30T14:59:19.766Z vite-node:client:execute /vitest-crash-reproduction/test/reproduction.test.ts
  vite:resolve 0.55ms @prisma/client -> /vitest-crash-reproduction/node_modules/@prisma/client/index.js +45ms
2023-03-30T14:59:19.768Z vite-node:client:native /vitest-crash-reproduction/node_modules/@prisma/client/index.js
2023-03-30T14:59:19.783Z prisma:tryLoadEnv  Environment variables not found at null
2023-03-30T14:59:19.783Z prisma:tryLoadEnv  Environment variables not found at undefined
2023-03-30T14:59:19.783Z prisma:tryLoadEnv  No Environment variables loaded
2023-03-30T14:59:19.785Z vite-node:client:native /vitest-crash-reproduction/node_modules/vitest/dist/index.js
2023-03-30T14:59:19.788Z prisma:tryLoadEnv  Environment variables not found at null
2023-03-30T14:59:19.788Z prisma:tryLoadEnv  Environment variables not found at undefined
2023-03-30T14:59:19.788Z prisma:tryLoadEnv  No Environment variables loaded
2023-03-30T14:59:19.788Z prisma:client  dirname /vitest-crash-reproduction/node_modules/.prisma/client
2023-03-30T14:59:19.788Z prisma:client  relativePath ../../../prisma
2023-03-30T14:59:19.788Z prisma:client  cwd /vitest-crash-reproduction/prisma
2023-03-30T14:59:19.789Z prisma:client  protocol graphql
2023-03-30T14:59:19.789Z prisma:client  clientVersion 4.12.0
2023-03-30T14:59:19.789Z prisma:client  clientEngineType library
2023-03-30T14:59:19.789Z prisma:client:libraryEngine  internalSetup
2023-03-30T14:59:19.790Z prisma:client:libraryEngine:loader  Searching for Query Engine Library in /vitest-crash-reproduction/node_modules/.prisma/client
2023-03-30T14:59:19.791Z prisma:client:libraryEngine:loader  loadEngine using /vitest-crash-reproduction/node_modules/.prisma/client/libquery_engine-darwin-arm64.dylib.node
2023-03-30T14:59:19.796Z prisma:client:libraryEngine  library starting
2023-03-30T14:59:19.803Z prisma:client:libraryEngine  library started
 · test/reproduction.test.ts (1)
2023-03-30T14:59:19.810Z prisma:client  Prisma Client call:
2023-03-30T14:59:19.811Z prisma:client  prisma.user.count({
  select: {
    _count: {
      select: {
        _all: true
      }
    }
  },
  where: {
    id: 1
  }
})
2023-03-30T14:59:19.811Z prisma:client  Generated request:
2023-03-30T14:59:19.811Z prisma:client  query {
  aggregateUser(where: {
    id: 1
  }) {
    _count {
      _all
    }
  }
}

2023-03-30T14:59:19.811Z prisma:client:libraryEngine  sending request, this.libraryStarted: true
2023-03-30T14:59:19.811Z prisma:client  Prisma Client call:
2023-03-30T14:59:19.811Z prisma:client  prisma.user.count({
  select: {
    _count: {
      select: {
        _all: true
      }
    }
  },
  where: {
    id: 1
  }
})
2023-03-30T14:59:19.811Z prisma:client  Generated request:
2023-03-30T14:59:19.812Z prisma:client  query {
  aggregateUser(where: {
    id: 1
  }) {
    _count {
      _all
    }
  }
}

 ❯ test/reproduction.test.ts (1)
   × likely crashes

⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯ Failed Tests 1 ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯

 FAIL  test/reproduction.test.ts > likely crashes
Error: Oh no!
 ❯ test/reproduction.test.ts:16:20
     14| 
     15|     // The issue seems related to a rejected promise happening while a query is running.
     16|     Promise.reject(new Error("Oh no!")),
       |                    ^
     17| 
     18|     // This line seems to make it more likely to crash, but it still does crash without it.

⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/1]⎯

 Test Files  1 failed (1)
      Tests  1 failed (1)
   Start at  09:59:19
   Duration  229ms (transform 23ms, setup 0ms, collect 32ms, tests 17ms)

thread 'tokio-runtime-worker' panicked at 'Expected weak reference to be valid.', query-engine/schema/src/lib.rs:38:24
stack backtrace:
   0:        0x139511ae4 - _napi_register_module_v1
   1:        0x138ed6510 - <unknown>
   2:        0x1394f0354 - _napi_register_module_v1
   3:        0x139514f2c - _napi_register_module_v1
   4:        0x139514b8c - _napi_register_module_v1
   5:        0x139515a74 - _napi_register_module_v1
   6:        0x1395155f0 - _napi_register_module_v1
   7:        0x139515560 - _napi_register_module_v1
   8:        0x13951553c - _napi_register_module_v1
   9:        0x1397995bc - _napi_register_module_v1
  10:        0x138eda1b4 - <unknown>
  11:        0x138eda178 - <unknown>
  12:        0x1397997b8 - _napi_register_module_v1
  13:        0x1394192c0 - _napi_register_module_v1
  14:        0x139342fcc - _napi_register_module_v1
  15:        0x139342768 - _napi_register_module_v1
  16:        0x138e03ef4 - <unknown>
  17:        0x138e05098 - <unknown>
  18:        0x138e1d9e8 - <unknown>
  19:        0x138e1c284 - <unknown>
  20:        0x138e0c470 - <unknown>
  21:        0x138e5a9f0 - <unknown>
  22:        0x138e39988 - <unknown>
  23:        0x138e44a70 - <unknown>
  24:        0x13952c3c0 - _napi_register_module_v1
  25:        0x1395378c4 - _napi_register_module_v1
  26:        0x13952b33c - _napi_register_module_v1
  27:        0x13952ad58 - _napi_register_module_v1
  28:        0x139530e3c - _napi_register_module_v1
  29:        0x139516e24 - _napi_register_module_v1
  30:        0x1b120606c - __pthread_deallocate
zsh: bus error  npm run test -- --run

In Prisma 4.11, I also received this trace (but was unable to get it again with 4.12):

thread '<unnamed>' panicked at 'assertion failed: `(left == right)`
  left: `1`,
 right: `0`: failed to delete napi ref', query-engine/query-engine-node-api/src/engine.rs:140:1
stack backtrace:
   0:        0x116d0a4f8 - _napi_register_module_v1
   1:        0x1166d0604 - <unknown>
   2:        0x116ce8604 - _napi_register_module_v1
   3:        0x116d0d944 - _napi_register_module_v1
   4:        0x116d0d5a4 - _napi_register_module_v1
   5:        0x116d0e47c - _napi_register_module_v1
   6:        0x116d0e008 - _napi_register_module_v1
   7:        0x116d0df78 - _napi_register_module_v1
   8:        0x116d0df54 - _napi_register_module_v1
   9:        0x116f8e98c - _napi_register_module_v1
  10:        0x116f8eb70 - _napi_register_module_v1
  11:        0x116f90ad8 - _napi_register_module_v1
  12:        0x11663ad34 - <unknown>
fatal runtime error: failed to initiate panic, error 5

The issue seems to be related to Vitest's threading features. If you set test: { threads: false } in the vite.config.ts, the issue no longer occurs (or becomes so rare that I've been unable to find a failure).

It's unclear to me if the root cause is in Vitest or Prisma, or perhaps a subtle interaction between the projects. I've tested Prisma v3.15 through 4.12 with Vitest 0.29.8 and received similar crashes. I've tested Vitest 0.24.0 through 0.29.8 and v0.24.4 appears to be the first affected version of vitest.

Potentially related issues:

How to reproduce

  1. Clone the reproduction repo: nakleiderer/vitest-crash-reproduction
  2. Setup a local postgres server able to respond to this connection string: postgresql://postgres:postgres@localhost:5432/postgres
    (or change the connection string in prisma/schema.prisma)
  3. Run npm install and npx prisma migrate
  4. Run 'npm test' (for watch mode) or npm test -- --run (for single test run)
  5. See error (you might need to repeat step 4, as this issue appears to depend on a race condition)

Expected behavior

I expect the test to fail without crashing.

Prisma information

datasource db {
  url      = "postgresql://postgres:postgres@localhost:5432/postgres"
  provider = "postgresql"
}

generator client {
  provider = "prisma-client-js"
}

// The exact schema appears to be irrelevant
model User {
  id Int @id @default(autoincrement())
}
import { PrismaClient } from "@prisma/client";
import { it } from "vitest";

export const prisma = new PrismaClient();

it("likely crashes", async () => {
  // This error seems to only occur if a connection has been established before the promise rejection below.
  // Removing this line will still reproduce the issue, but it might be more intermittent (maybe, I didn't test this thoroughly)
  await prisma.$connect();

  await Promise.all([
    // The exact query used doesn't seem to matter. I chose count because it seems more trivial.
    prisma.user.count({ where: { id: 1 } }),

    // The issue seems related to a rejected promise happening while a query is running.
    Promise.reject(new Error("Oh no!")),

    // This line seems to make it more likely to crash, but it still does crash without it.
    prisma.user.count({ where: { id: 1 } }),
  ]);
});

Environment & setup

  • Database: PostgreSQL
  System:
    OS: macOS 13.2.1 (22D68)
    CPU: (10) arm64 Apple M1 Max
    Memory: 2.16 GB / 64.00 GB
    Shell: 5.8.1 - /bin/zsh
  Binaries:
    Node: 18.13.0 - ~/.asdf/installs/nodejs/18.13.0/bin/node
    npm: 8.19.3 - ~/.asdf/plugins/nodejs/shims/npm
  Browsers:
    Chrome: 111.0.5563.146
    Firefox: 108.0.1
    Safari: 16.3
  npmPackages:
    @prisma/client: ^4.12.0 => 4.12.0 
    prisma: ^4.12.0 => 4.12.0 
    vitest: ^0.29.8 => 0.29.8 

Prisma Version

prisma                  : 4.12.0
@prisma/client          : 4.12.0
Current platform        : darwin-arm64
Query Engine (Node-API) : libquery-engine 659ef412370fa3b41cd7bf6e94587c1dfb7f67e7 (at node_modules/@prisma/engines/libquery_engine-darwin-arm64.dylib.node)
Migration Engine        : migration-engine-cli 659ef412370fa3b41cd7bf6e94587c1dfb7f67e7 (at node_modules/@prisma/engines/migration-engine-darwin-arm64)
Format Wasm             : @prisma/prisma-fmt-wasm 4.12.0-67.659ef412370fa3b41cd7bf6e94587c1dfb7f67e7
Default Engines Hash    : 659ef412370fa3b41cd7bf6e94587c1dfb7f67e7
Studio                  : 0.483.0

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions