prisma: ENOENT error when running prisma as /api in next.js

I want to run prisma inside next.js as a /api route. When I was setting it up at first only with the graphql-auth example everything was working fine (beside some problems with typegen with photon, but there’s already an issue). Then I changed the schema and added some resolvers and objectTypes and when I wanted to start it again, when going to the route I get the output:

[Error: ENOENT: no such file or directory, mkdir] {
  errno: -2,
  code: 'ENOENT',
  syscall: 'mkdir'
}

and I cannot query the server: "error": "JSON.parse: unexpected character at line 1 column 1 of the JSON data"

When running the same files as a standalone server(with what graphql-auth example provides), it’s running fine.

Not sure if it’s related to next.js or not, I tried turning on debug on photon and apollo-server, but the only thing I got is: getos { platform: 'darwin', libssl: undefined } +0ms

Happy to provide more info if needed

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Comments: 15 (8 by maintainers)

Most upvoted comments

Hey everyone 👋,

@huv1k gave me a workaround. You can create a next.config.js file, and set the following env variable:

// next.config.js
module.exports = {
  env: {
    PROJECT_DIRNAME: __dirname,
  },
}

Then, use that env variable instead of __dirname

import { makeSchema } from 'nexus-prisma'
import { join } from 'path'

const schema = makeSchema({
  outputs: {
    typegen: join(process.env.PROJECT_DIRNAME, 'typegen.ts'),
    schema: join(process.env.PROJECT_DIRNAME, 'schema.ts'),
  }
})

It’s not great, but at least it’s a working workaround!

Thanks, everyone for posting the information!

After looking into your reproduction @BjoernRave , I found, that the problem here has nothing to do with prisma2, but it’s the combination of next.js and nexus, which doesn’t play well.

The problem is, that next.js replaces __dirname with /. This will inevitably make tools fail that rely on it. There were efforts on the Next.js side to fix that, but they got deprioritized.

Concretely, the line https://github.com/prisma-labs/nexus/blob/develop/examples/nexus-prisma/src/index.ts#L144

    schema: path.join(__dirname, './generated/schema.graphql'),

will be rewritten to path.join('/', './generated/schema.graphql') which resolves to //generated/schema.graphql.

Nexus then wants to write there in https://github.com/prisma-labs/nexus/blob/develop/src/typegenMetadata.ts#L101

How can you find that out without the stack trace? This small hack helps getting the stack trace back for mkdir:

import fs from 'fs'

const oldMkDir: any = fs.mkdir
;(fs as any).mkdir = (...args: any[]) => {
  const err = new Error()
  console.error(`Calling mkdir: ${err.stack}`)
  console.error(`dirname ${__dirname}`)
  return oldMkDir(...args)
}

So a separate issue is, that the stack trace is eaten, which is very likely also a Next.js problem, as nexus just acts a library in this situation.

TL;DR How to get around this problem?

For now, you can e.g. remove the outputs configuration for the makeSchema function of nexus:

export const schema = makeSchema({
  types,
  plugins: [nexusPrismaPlugin()],
  // outputs: {
  //   schema: __dirname + '/generated/schema.graphql',
  //   typegen: __dirname + '/generated/nexus.ts',
  // },
  typegenAutoConfig: {
    sources: [
      {
        source: '@prisma/photon',
        alias: 'photon',
      },
      {
        source: require.resolve('./context'),
        alias: 'Context',
      },
    ],
    contextType: 'Context.Context',
  },
})

You can also try the workaround posted here: https://github.com/zeit/next.js/issues/8251#issuecomment-547702744

I found a different approach to this:

const getPath = (fileName: string) =>
  path.join(process.cwd(), "generated", fileName);

// then use it to genetrate the output
    nexusPrismaPlugin({
      outputs: {
        typegen: getPath("nexusPrisma.ts")
      }
    })

@pantharshit00 okay, can I add you as a collaborator to my github project for you to see?