prisma: Prisma Edge Client + Data Proxy/Accelerate + CF Worker `process not defined`

Bug description

Getting process not found error when deploying the prisma Edge client to Cloudflare pages. Isn the Edge client supposed to prevent this error from happening? I am only using the client in SvelteKit Endpoints https://kit.svelte.dev/docs/routing#endpoints

NOTE: I am using dot-env package to run the local dev script in package.json as prisma cannot find my .env DATABASE_URL var without this command (Maybe this is related to the issue?)

Err Log:

{ text: 'Uncaught ReferenceError: process is not defined\n' + ' at line 8755 in node_modules/.prisma/client/edge.js\n' + ' at line 16 in __require2\n' + ' at line 8768 in node_modules/@prisma/client/edge.js\n' + ' at line 16 in __require2\n' + ' at line 8774\n' + ' at line 8789\n' + ' [code: 10021]' }

How to reproduce

  1. Set up Prisma data-proxy in SvelteKit following this instructions https://www.prisma.io/docs/concepts/data-platform/data-proxy
  2. Deploy to CF pages and see that it builds successfully, but when visiting a page it will have the process not found error

You should be using the Edge Client and --data-proxy option with npx prisma generate. And your database_url should start wit prisma://

Expected behavior

I’m not executing code that is meant for the server on the client so I dont understand why this error is happening

Prisma information

I have a demo of the issue here https://github.com/vidiabtc/sveltekit-test

Environment & setup

  • OS: MacOS–>
  • Database: MySQL
  • Node.js version: v16.7.0

Prisma Version

		"prisma": "^3.15.1",
		"@prisma/client": "^3.15.1",

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Reactions: 5
  • Comments: 29 (7 by maintainers)

Commits related to this issue

Most upvoted comments

This issue is now fixed and the fix will be released in Prisma 4.2.0 on Tuesday, Aug 9.

Prisma won’t crash trying to access process.env when using the new Module Workers format of Cloudflare Workers (including the SvelteKit use case). You shouldn’t need the workaround with node_compat shared earlier in this thread anymore.

Please note that with Module Workers there are no global bindings for secrets and environment variables that Prisma could use (see this comment). Instead, the env object is passed as a parameter to the fetch handler:

interface Env {
  DATABASE_URL: string
}

export default {
  async fetch(request: Request, env: Env /* <-- here it is! */, ctx: ExecutionContext): Promise<Response> {
    // ...
  }
}

See Cloudlfare docs for more details: https://developers.cloudflare.com/workers/learning/migrating-to-module-workers/

The implications are:

  1. Prisma Client must be created inside the handler and not on the module level. This is a Cloudflare limitation which we cannot work around. You can cache the created Prisma Client instance using a module-level variable though, and only create it inside the handler once if it’s null.

  2. The datasource URL has to be passed like this:

    const prisma = new PrismaClient({
      datasources: {
        db: {
          url: env.DATABASE_URL
        }
      }
    })
    

    We may come up with an API to make it less verbose in the future, but for now overriding the datasource URL with the value from the env parameter of the fetch handler is the official guideline when using Prisma with Module Workers. We will work on the guide and add it to the documentation.

Note that this doesn’t apply to the old Service Workers format — everything should work as usual there.

Finally, and this is not strictly related to this issue, we added an error to assist you debugging a missing environment variable. Instead of not very helpful InvalidDatasourceError: Could not parse URL of the datasource you will get more explicit InvalidDatasourceError: Datasource "db" references an environment variable "DATABASE_URL" that is not set.

In the context of Cloudflare Module Workers, when overriding the datasource URL manually, you are more likely to see this error if you forgot to add a secret using wrangler: Error: Invalid value undefined for datasource "db" provided to PrismaClient constructor. This is not a new error, we have supported it before.

However, the new error will hopefully be helpful when using Service Workers, when not using Cloudflare Workers at all, or if you didn’t override the datasource with Module Workers.

If you’re using Wrangler@2 and you’re using a .toml file. you can add this property to get around it. Wrangler spits a nasty warning out at you, but to this point I haven’t had an issue in production.

# Add polyfills for node builtin modules and globals
node_compat = true

Here’s the docs for it: https://developers.cloudflare.com/workers/wrangler/configuration/. Just scroll down until you see node_compat

Just waiting until Prisma fixes this issue.

I’ve investigated the issue last week, but I didn’t write an update here, sorry for that!

Regarding the original issue, the problem happens not just with SvelteKit specifically, but with the new Module Worker format of Cloudflare Workers in general. Prisma assumes the Service Worker format, which used to have global bindings to the environment variables, secrets and KV namespaces, but it doesn’t work like that in the module workers that receive env and ctx as parameters of the request handler function.

One part of the issue is that the fallback paths where we try to retrieve the value of an environment variable in different ways should be more resilient and shouldn’t explode when assumptions fail.

Another part of the issue is supporting loading the DATABASE_URL in Module Workers. It will not be possible to make just const prisma = new PrismaClient() work because no equivalent of environment variables exists in the global scope, something will have to be passed to the constructor.

I can see two ways to approach this.

  1. Without adding new APIs, it should be possible to manually override the datasource URL with a value from env which Prisma doesn’t have access to by itself:

    const prisma = new PrismaClient({
      datasources: {
        db: {
          url: env.DATABASE_URL
        }
      }
    })
    

    (While this doesn’t currently work in Prisma 4.1.0, the fix for this will be released in 4.2.0, we already fixed it in the context of another issue).

    We may document this as a requirement for the Module Workers, at least as a temporary solution.

  2. We can add an API to make it a little bit less verbose and get the closest thing possible to how it works in other environments:

    const prisma = new PrismaClient({ env })
    

Finally, we should think about how we can help debug the DATABASE_URL not being picked up, regardless of whether it happens because of us not picking it up properly or a configuration issue in the project.

@vladinator1000 overriding the datasource URL in PrismaClient constructor argument is currently not working with the Data Proxy client, the fix for that is not merged yet, but it will be released in Prisma 4.2.0.

@yamiteru worked for me, check this video https://youtu.be/4nacpK9odjs

If you can not get it to work, please open an issue @yamiteru and include all the information the issue template asks for. We are more than happy to take a look. We can always miss individual combinations.

@drewdecarme Thanks! Confirmed it works!

I don’t understand how this issue moved from process not defined to something else.

I’m running into the process not defined error when deploying with Wrangler@2

Sorry for hijacking the thread @jjjrmy, @alexanderzinolidis For the process thing, would a polyfill work for you?

I have this setup

// polyfills.js
// Prisma uses the process global so we need to enable it https://github.com/evanw/esbuild/issues/1374#issuecomment-861801905
export var process = {
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy
  env: new Proxy(
    {},
    {
      get: () => '',
    },
  ),
}

Then I inject it in my ESBuild config:

const path = require('path')
const { build } = require('esbuild')
const alias = require('esbuild-plugin-alias')

async function buildWorker() {
  try {
    const mode = globalThis.ENVIRONMENT || 'development'

    const result = await build({
      bundle: true,
      minify: mode === 'production',
      sourcemap: true,
      metafile: true,
      treeShaking: true,
      format: 'esm',
      target: 'esnext',
      entryPoints: [path.join(__dirname, '../server/worker.ts')],
      outdir: path.join(__dirname, '../dist'),
      inject: [path.join(__dirname, 'polyfills.js')], // <--- inject here
      plugins: [
        alias({
          '@prisma/client': require.resolve('@prisma/client'),
        }),
      ],
    })
  } catch (err) {
    console.error(err)
    process.exitCode = 1
  }
}

buildWorker()

Before the fix is officially released - is there some workaround maybe?

After diving through the documentation a little bit more for Cloudflare Workers, you can add a node_compat field to your wrangler.toml and that should get you passed the process issue. Again, it’s still something that we technically shouldn’t have to account for since this is an edge environment, not a node one.

https://developers.cloudflare.com/workers/wrangler/configuration/#configure-wranglertoml