Skip to content

Vitest environment: ZenStack enhance() causes TypeError: PrismaClientKnownRequestError is not a constructor #2134

@kent8192

Description

@kent8192

Environment

  • Framework: NestJS v11.1.1
  • ZenStack: 2.15.0
  • Prisma: 6.8.2
  • Database: PostgreSQL
  • Test runner: Vitest v3.1.4
  • Node.js: ≥18.x
  • OS: (e.g.) macOS / Linux / Windows

Summary

When running tests under Vitest, the ZenStack-enhanced Prisma client fails to correctly expose PrismaClientKnownRequestError, resulting in:

TypeError: prismaModule.PrismaClientKnownRequestError is not a constructor

Expected Behavior

  • ZenStack’s enhance() should wrap the Prisma client and apply access-control policies without interfering with Prisma’s error constructors.

Actual Behavior

  • Under Vitest (with process.env.VITEST = true), invoking enhance() leads to TypeError: … is not a constructor.
  • Bypassing enhance() when Vitest is detected makes tests pass again, indicating the problem lies in ZenStack’s enhancer.

Steps to Reproduce

  1. Create a NestJS service that extends PrismaClient and applies ZenStack’s enhance():

    // prisma.service.ts
    @Injectable()
    export class PrismaService extends PrismaClient {
      constructor(@Inject(Argon2idService) private readonly argon2: Argon2idService) {
        super();
        const extended = this.$extends(hashPasswordExtension(this.argon2));
        const client = !process.env.VITEST
          ? enhance(extended, undefined, { logPrismaQuery: true })
          : extended;
        Object.assign(this, client);
      }
      async onModuleInit() { await this.$connect(); }
      async onModuleDestroy() { await this.$disconnect(); }
    }
  2. Write a Vitest test that triggers a Prisma error (e.g. duplicate‐key).

  3. Run tests with VITEST=true pnpm vitest.

  4. Observe the constructor error instead of a Prisma error instance.

Reproduction Code

import { Injectable, Inject } from '@nestjs/common';
import { PrismaClient } from '@generated/prisma/index.mts';
import { enhance } from '@zenstackhq/runtime';
import { hashPasswordExtension } from './prisma.extentions.ts';
import { Argon2idService } from '@libs/argon2id/argon2id.service.ts';

@Injectable()
export class PrismaService extends PrismaClient {
  constructor(
    @Inject(Argon2idService) private readonly argon2: Argon2idService,
  ) {
    super();
    const extended = this.$extends(hashPasswordExtension(this.argon2));
    // Disable ZenStack enhancement when running Vitest
    const client = !process.env.VITEST
      ? enhance(extended, undefined, { logPrismaQuery: true })
      : extended;
    Object.assign(this, client);
  }

  async onModuleInit() {
    await this.$connect();
  }

  async onModuleDestroy() {
    await this.$disconnect();
  }
}

Error Log

> pnpm nx run backend:vitest
…
> vitest run
  RUN  auth.service.spec.ts
TypeError: prismaModule.PrismaClientKnownRequestError is not a constructor
    at Object.<anonymous> (node_modules/@zenstackhq/runtime/dist/index.js:…)
    at Module._compile (internal/modules/cjs/loader.js:…)
    …

Workaround

Guard the call to enhance() by checking process.env.VITEST and falling back to the unenhanced client in tests.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions