nextauthjs / next-auth

Authentication for the Web.
https://authjs.dev
ISC License
24.26k stars 3.38k forks source link

Intermittent FetchError: invalid json response body #4590

Closed simonecervini closed 2 years ago

simonecervini commented 2 years ago

Environment

  System:
    OS: macOS 12.2.1
    CPU: (4) x64 Intel(R) Core(TM) i5-7360U CPU @ 2.30GHz
    Memory: 222.53 MB / 8.00 GB
    Shell: 5.8 - /bin/zsh
  Binaries:
    Node: 16.13.0 - ~/.nvm/versions/node/v16.13.0/bin/node
    Yarn: 1.22.17 - /usr/local/bin/yarn
    npm: 8.1.0 - ~/.nvm/versions/node/v16.13.0/bin/npm
  Browsers:
    Chrome: 101.0.4951.64
    Firefox: 100.0.1
    Safari: 15.3
  npmPackages:
    @next-auth/mongodb-adapter: ^1.0.0 => 1.0.0
    mongodb: ^4.5.0 => 4.5.0
    next: ^12.1.0 => 12.1.0
    next-auth: ^4.3.4 => 4.3.4
    react: 17.0.2 => 17.0.2
    react-query: ^3.18.1 => 3.34.0

Reproduction URL

/api/auth/session

Describe the issue

getSession() called server side sometimes fails with the following error:

[next-auth][error][CLIENT_FETCH_ERROR] 
https://next-auth.js.org/errors#client_fetch_error invalid json response body at [MY DOMAIN]/api/auth/session reason: Unexpected token < in JSON at position 0 {
  error: {
    message: 'invalid json response body at [MY DOMAIN]/api/auth/session reason: Unexpected token < in JSON at position 0',
    stack: 'FetchError: invalid json response body at [MY DOMAIN]/api/auth/session reason: Unexpected token < in JSON at position 0\n' +
      '    at /var/task/node_modules/next/dist/compiled/node-fetch/index.js:1:49606\n' +
      '    at runMicrotasks (<anonymous>)\n' +
      '    at processTicksAndRejections (node:internal/process/task_queues:96:5)',
    name: 'FetchError'
  },
  ...
}

Errors are occurring in the production environment: the app is deployed on Vercel and connected to an Atlas M0 MongoDB cluster (it's the free shared cluster of MongoDB Atlas).

The app works 90% of the time and the errors occur very randomly. I use react-query (with Query Retries enabled) to make requests to API endpoints which uses getSession for authentication and usually, after the first retry, the failed request doesn't fail anymore. With the retry option enabled, users do not experience any problem apart from slower loading because of duplicated requests.

My debug considerations

The application has low traffic, but I have multiple E2E tests running every 5 minutes that should also avoid cold starts I believe, but I'm not very sure about how this works. I also have general uptime checks running every 3 minutes.

How to reproduce

Intermittent and difficult to reproduce. I test my API routes every 5 minutes and i got 8 errors in the last 24 hours. The next-auth setup is very simple:

const nextAuthUrl = process.env.NEXTAUTH_URL ?? '';

const getMagicLink = ({ token: _token, email: _email }: { token: string; email: string }) => { [...] };

export default NextAuth({ secret: process.env.NEXTAUTH_SECRET, adapter: MongoDBAdapter(clientPromise), providers: [ EmailProvider({ maxAge: 24 60 60, // 24h sendVerificationRequest: async ({ identifier: email, token }) => { await sendEmail({ to: email, templateName: 'next-auth-magic-link', vars: [ { name: 'MAGICLINK', content: getMagicLink({ email, token }), }, ], }); }, }), ], pages: { signIn: '/login', error: '/login', }, });


- mongodb.ts

import { MongoClient } from 'mongodb';

const uri = process.env.MONGODB_CONNECTION_STRING;

let client; let clientPromise: Promise;

if (!uri) { throw new Error('process.env.MONGODB_CONNECTION_STRING is falsy'); }

if (process.env.NODE_ENV === 'development') { // In development mode, use a global variable so that the value // is preserved across module reloads caused by HMR (Hot Module Replacement). if (!(global as any)._mongoClientPromise) { client = new MongoClient(uri); (global as any)._mongoClientPromise = client.connect(); } clientPromise = (global as any)._mongoClientPromise; } else { // In production mode, it's best to not use a global variable. client = new MongoClient(uri); clientPromise = client.connect(); }

// Export a module-scoped MongoClient promise. By doing this in a // separate module, the client can be shared across functions. export default clientPromise;



### Expected behavior

No FetchError should occur
balazsorban44 commented 2 years ago

Duplicate of https://github.com/nextauthjs/next-auth/issues/4553