prisma: Bun: Prisma fails silently when seeding with bun with top level async function

Bug description

I’m using Prisma in an app running on Bun.sh + Elysia. I just added Prisma and configured a seeding script that looks like this:

import { PrismaClient } from "@prisma/client";

const prisma = new PrismaClient({
    log: [
      {
        emit: 'event',
        level: 'query',
      },
      {
        emit: 'stdout',
        level: 'error',
      },
      {
        emit: 'stdout',
        level: 'info',
      },
      {
        emit: 'stdout',
        level: 'warn',
      },
    ],
  })
  
  prisma.$on('query', (e) => {
    console.log('Query: ' + e.query)
    console.log('Params: ' + e.params)
    console.log('Duration: ' + e.duration + 'ms')
  })
async function main() {
  const client = await prisma.client.create({
    data: data, // ommited for brevity
  });

  const codes = await prisma.countryCode.createMany({
    data: countryCodes, // ommited for brevity
  });
}

main()
  .then(async () => {
    console.log("Successfully seeded DB");
    await prisma.$disconnect();
  })
  .catch(async (e) => {
    console.error(e);
    await prisma.$disconnect();
    process.exit(1);
  });

The problem is that when I run bunx prisma db seed, the process fails silently on the first create operation. No errors, nothing. The logs output this:

bunx prisma db seed
  prisma:engines  binaries to download libquery-engine, schema-engine +0ms
  prisma:loadEnv  project root found at /Users/.../package.json +0ms
  prisma:tryLoadEnv  Environment variables loaded from /Users/.../.env +0ms
Environment variables loaded from .env
  prisma:migrate:seed  {
  prismaConfig: {
    data: { seed: 'bun prisma/seed.ts' },
    packagePath: '/Users/.../package.json'
  }
} +0ms
Running seed command `bun prisma/seed.ts` ...
  prisma:tryLoadEnv  Environment variables loaded from /Users/.../.env +0ms
  prisma:client  checkPlatformCaching:postinstall undefined +0ms
  prisma:client  checkPlatformCaching:ciName undefined +0ms
  prisma:tryLoadEnv  Environment variables loaded from /Users/.../.env +26ms
  prisma:client  dirname /Users/.../node_modules/.prisma/client +0ms
  prisma:client  relativePath ../../../prisma +0ms
  prisma:client  cwd /Users/.../prisma +0ms
  prisma:client  clientVersion 5.3.1 +0ms
  prisma:client:libraryEngine  internalSetup +0ms
  prisma:client  Prisma Client call: +5ms
  prisma:client  prisma.client.create({
  data: {
    ....
  }
}) +1ms
  prisma:client  Generated request: +0ms
  prisma:client  {
  "modelName": "Client",
  "action": "createOne",
  "query": {
    "arguments": {
      "data": {
        ...
      }
    },
    "selection": {
      "$composites": true,
      "$scalars": true
    }
  }
}
 +0ms
  prisma:client:libraryEngine  sending request, this.libraryStarted: false +6ms
  prisma:client:engines:resolveEnginePath  enginePath /Users/.../node_modules/.prisma/client/libquery_engine-darwin-arm64.dylib.node +0ms
  prisma:client:libraryEngine  library starting +27ms

🌱  The seed command has been executed.
  prisma:getConfig  Using getConfig Wasm +0ms
  prisma:getConfig  config data retrieved without errors in getConfig Wasm +8ms

And that’s it, it finishes the process but nothing else happens.

How to reproduce

  1. Use a bun.sh environment with Postgresql and integrate Prisma.
  2. Create a seeding script.
  3. Insert some data
  4. See described behavior.

Expected behavior

Prisma should insert the records or generate an error if something goes wrong.

Prisma information

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

datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
}
Code added in the main body of this issue.

Environment & setup

  • OS: macOS
  • Database: PostgreSQL
  • Node.js version: v20.6.1

Prisma Version

5.3.1

About this issue

  • Original URL
  • State: open
  • Created 9 months ago
  • Reactions: 9
  • Comments: 21 (9 by maintainers)

Most upvoted comments

Okay, this rang a bell so I dug into our topic: bun issues:

https://github.com/prisma/prisma/issues/21108

This is being tracked over at bun at https://github.com/oven-sh/bun/issues/3137

So the solution is to use this script with a top level await instead of the main function:

import { PrismaClient } from "@prisma/client"

const prisma = new PrismaClient()

try {
    console.log("main")
    await prisma.user.create({
        data:
        {
            name: "John Dough",
            email: `john-${Math.random()}@example.com`
        },
    })
    console.log("after create")
    const count = await prisma.user.count()

    console.log(`There are ${count} users in the database.`)
} catch (error) {
    console.error(error);
    await prisma.$disconnect();
    process.exit(1);
}

@mathieuarthur

By default no main function is needed in this languages, so why use it ?

Top-level await is only possible in native ESM while lots of folks still use CommonJS and transpile ESM syntax into it, doubly so back in the day when these docs were written. Wrapping everything into an async function ensures everyone can copy this code as is and it will always work.

Tbh I don’t think bun should fix anything

This is a real bug that certainly has to be fixed. Regardless of your stylistic preferences, this is incorrect behaviour, and can lead to issues in many other scenarios as well.

Spent hours figuring this out. It would be great if the Prisma documentation would mention something about this. It seems the issue exist only for bun.

I ended up just awaiting the main function like so:

await main()
  .catch((e) => {
    console.error(e);
    process.exit(1);
  })
  .finally(async () => {
    await prisma.$disconnect();
    console.log("Disconnected from database.");
  });

I like this a bit better as it stays closer to the source documentation using promise chaining and disconnects in the finally block.

I have the similar issue on bun v1.0.35. Using await on the main function call solves it.

https://github.com/oven-sh/bun/issues/3137#issuecomment-1927726343

As of Bun v1.0.26, this has been fixed. If you’re still experiencing this issue, let us know and we’ll re-open the issue.

❯ bun index.ts
foo
cheese
0

Can someone confirm?

Oh yeah my bad, tbh I didn’t think anyone would still use CommonJS. My bad you are right in this case !

As I talked with js expert, he found really strange that in a js / ts you used a main function for the seeder (cf: see your documentation )

By default no main function is needed in this languages, so why use it ?

As bun work pretty much like node / native js we shouldn’t call the top level await a “workaround” but the effective and intended way in js to perform this.

Tbh I don’t think bun should fix anything (maybe add the good behaviour inside a function but it is not mandatory) and you should edit the documentation to follow what the new bun documentation tell, so no “main” function

Like this :

import { PrismaClient } from "@prisma/client";

const prisma = new PrismaClient();

// create a new user
await prisma.user.create({
  data: {
    name: "John Dough",
    email: `john-${Math.random()}@example.com`,
  },
});

// count the number of users
const count = await prisma.user.count();
console.log(`There are ${count} users in the database.`);

Coming from the official doc / link in my comment.

Hello again! I did some experimentation, and these are my findings:

  1. I removed everything Bun-related from the script and ran it with node. It behaved as expected.
  2. I put the Bun imports back into the script (note to @aqrln, I shared an abridged version of the script; I was using Bun.CryptoHasher to generate some hashes as part of the seeding), and that’s when trouble started.
  3. I tried to make ts-node and bun work together by using bunx prisma db seed and ts-node prisma/seed.ts in my package.json, but this led nowhere. First, ts-node couldn’t resolve Bun, then after some tinkering with the compileOptions it worked, but other libraries failed to be resolved. Either the dependencies broke, or the module rejected my code.

Thus, I don’t believe the issue is related to Prisma. I think it is related to how Bun runs scripts and its incompatibility with ts-node. I think I’ll ditch Bun in favor of Node until this behaves properly and avoid you guys wasting any more time on this.

I can’t test it with node, the script uses some of Bun’s cryptography libraries to generate the data for seeding. If I try to run it with node, I’d have to rewrite it.