Issue encountered with Next.js 13.4 and NextAuth: A Type Error stating that 'AuthOptions' is not compatible with type 'never'

Currently, I am in the process of developing a Next.js 13.4 project and attempting to configure NextAuth using the app/router. Unfortunately, I have encountered a type error that I am struggling to troubleshoot.

Below is my route.ts file:

import NextAuth, { AuthOptions } from "next-auth";
import DiscordProvider from "next-auth/providers/discord";

export const authOptions: AuthOptions = {
  providers: [
    DiscordProvider({
      clientId: process.env.CLIENT_ID as string,
      clientSecret: process.env.CLIENT_SECRET as string,
    }),
  ],
  session: {
    strategy: "jwt",
  },
  secret: process.env.NEXTAUTH_SECRET,
}

const handler = NextAuth(authOptions);

export { handler as GET, handler as POST }

When I run 'npm run build', I receive the following error message:

- info Linting and checking validity of types ...Failed to compile.

.next/types/app/api/auth/[...nextauth]/route.ts:8:13
Type error: Type 'OmitWithTag<typeof import("C:/Users/Luk/Documents/Workspace/zerotwo-dash/src/app/api/auth/[...nextauth]/route"), "GET" | "POST" | "HEAD" | "OPTIONS" | "PUT" | "DELETE" | "PATCH" | "config" | ... 6 more ... | "runtime", "">' does not satisfy the constraint '{ [x: string]: never; }'.
  Property 'authOptions' is incompatible with index signature.
    Type 'AuthOptions' is not assignable to type 'never'.

   6 |
   7 | // Check that the entry is a valid entry
>  8 | checkFields<Diff<{
     |             ^
   9 |   GET?: Function
  10 |   HEAD?: Function
  11 |   OPTIONS?: Function

I am currently stuck and unsure of what is causing this issue. I have reviewed the 'AuthOptions' on the NextAuth GitHub page but cannot find any discrepancies with my code.

If anyone has any insights or suggestions on how to resolve this error, I would greatly appreciate it. Thank you in advance!

Answer №1

After coming across a similar issue, I took matters into my own hands and resolved it. I decided to tackle the problem by creating a new file named @/utils/authOptions.ts:

import { NextAuthOptions } from "next-auth";
import DiscordProvider from "next-auth/providers/discord";

export const authOptions: NextAuthOptions = {
    providers: [
        DiscordProvider({
            clientId: process.env.CLIENT_ID as string,
            clientSecret: process.env.CLIENT_SECRET as string,
        }),
    ],
    session: {
        strategy: "jwt",
    },
    secret: process.env.NEXTAUTH_SECRET,
}

Next, I utilized this new file in @/api/auth/[...nextauth]/route.ts:

import { authOptions } from "@/utils/authOptions";
import NextAuth from "next-auth/next";

const handler = NextAuth(authOptions);

export { handler as GET, handler as POST };

I made some adjustments in the imports, particularly by changing 'import NextAuth from "next-auth/next"'. Strangely enough, I'm not entirely sure why this solution worked, but it did. Even reverting back to the previous import setup in my route.ts file did not resolve the issue. Only separating the imports in this specific manner seemed to do the trick...

Answer №2

The issue at hand involves exporting the authOptions with handlers in the route.ts file for Next.js 13.4+. By simply excluding the export from the authOptions, the problem is resolved. This is why separating the authOptions worked :).

route.ts -->

import NextAuth, { AuthOptions } from "next-auth";
import DiscordProvider from "next-auth/providers/discord";

// Export removed here
const authOptions: AuthOptions = {
  providers: [
    DiscordProvider({
      clientId: process.env.CLIENT_ID as string,
      clientSecret: process.env.CLIENT_SECRET as string,
    }),
  ],
  session: {
    strategy: "jwt",
  },
  secret: process.env.NEXTAUTH_SECRET,
}

const handler = NextAuth(authOptions);

export { handler as GET, handler as POST }

If you need to access authOptions elsewhere, you can do so like this --->

import NextAuth, { AuthOptions } from "next-auth";
import DiscordProvider from "next-auth/providers/discord";

// Export removed here
const authOptions: AuthOptions = {
  providers: [
    DiscordProvider({
      clientId: process.env.CLIENT_ID as string,
      clientSecret: process.env.CLIENT_SECRET as string,
    }),
  ],
  session: {
    strategy: "jwt",
  },
  secret: process.env.NEXTAUTH_SECRET,
}

const handler = NextAuth(authOptions);

export { handler as GET, handler as POST, authOptions }

Answer №3

After trying the accepted solution without success in my Next.js 14.0.4 and Next-Auth 5.0.0-beta.5 setup, I decided to come up with my own workaround.

Instead of moving the authOptions elsewhere, all I did was simply export the two handlers.

const handler = NextAuth({
  /* ... your config ... */
});

export const GET = handler.handlers.GET;
export const POST = handler.handlers.POST;

Answer №4

I encountered a similar issue and was able to resolve it by using the phrase "as never" in the following manner:

import NextAuth from 'next-auth';
import { authConfig } from '@/app/lib/authConfig';

export const handler = NextAuth(authConfig) as never;

export { handler as GET, handler as POST };

import CredentialsProvider from 'next-auth/providers/credentials';

export const authConfig = {
    providers: [
        CredentialsProvider({
            name: 'Credentials',
            credentials: {
                username: {
                    label: 'Email Address',
                    type: 'text',
                    placeholder: 'Email address...'
                },
                password: {
                    label: 'Password',
                    type: 'password',
                    placeholder: 'Password...'
                },

            },
            async authorize(credentials, req) {
                // Add your authorization logic here
                
                // return {
                //     name: ...
                //     email: ...
                //    id: ...
                // };
            }
        })
    ]
};

Answer №5

Here is where I handle my route: api/auth/[[...nextauth]]/route.ts

import { authOptions } from "@/lib/auth";
import NextAuth from "next-auth/next";

const handler = NextAuth(authOptions);
export { handler as GET, handler as POST };

This is my auth configuration in lib/auth.ts

import type { NextAuthOptions } from "next-auth";
import CredentialsProvider from "next-auth/providers/credentials";
import { prisma } from './client'
import { compare } from "bcrypt";
import { User } from "@prisma/client";
import NextAuth, { getServerSession } from "next-auth";

export const authOptions: NextAuthOptions = {
   session: {
     strategy: "jwt",
   },
   providers: [
     CredentialsProvider({
       name: "Sign in",
       credentials: {
         email: {
           label: "Email",
           type: "email",
           placeholder: "<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="c0a5b8a1adb0aca580a5b8a1adb0aca5eea3afad">[email protected]</a>",
         },
         password: { label: "Password", type: "password" },
       },
       async authorize(credentials) {
          if (!credentials) {
             return null;
           }
   
           if (!credentials?.email || !credentials.password) {
             return null
           }
   
           const user = await prisma.user.findUnique({
             where: {
               email: credentials.email
             }
           })
   
           if (!user) {
             return null
           }
   
           const isPasswordValid = await compare(
             credentials.password,
             user.password
           )
   
           if (!isPasswordValid) {
             return null
           }
   
           return {
             id: user.id + '',
             email: user.email,
             name: user.name,
             role: user.role,
             avatarUrl: user.avatarUrl
           }
       },
     }),
   ],
   callbacks: {
     jwt: ({token, user, session, trigger}) => {
       // console.log('JWT Callback', { token, user })
       // console.log('JWT Callback', { token, user, trigger, session });
       
       if (trigger === 'update' && session?.user) {
         return {
           ...token,
           name: session.user.name || token.name,
           email: session.user.email || token.email,
           avatarUrl: session.user.avatarUrl || token.avatarUrl,
         }
       }
 
       if(user) {
         const u = user as unknown as User
         return {
           ...token,
           id: u.id,
           role: u.role,
           avatarUrl: u.avatarUrl
         }
       }
       
       return token
     },
     session: ({session, token, user}) => {
       // console.log('Session Callback', { session, token })
       return {
         ...session,
         user: {
           ...session.user,
           id: token.id,
           role: token.role,
           avatarUrl: token.avatarUrl
         }
       }
       
     },
      
   },
   pages: {
    signIn: '/auth/signin',
   },
 
 };
 export const getServerAuthSession = () => getServerSession(authOptions);

This solution resolved my issue

Answer №6

To utilize authOptions in a different file, simply import it. This method should prove effective.👌🏼

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Unable to retrieve the request body in a basic nextjs API request

Currently, I am initiating this call from my local nextjs frontend application. const handleApiCall = async () => { const requestOptions = { method: "POST", body: JSON.stringify({ hello: "world" }), headers: { "content-ty ...

Tips for validating and retrieving data from a radio button paired with an input box in reactjs

I'm diving into the world of React and facing a challenge with multiple radio buttons that have associated input fields, like in this image: https://i.stack.imgur.com/Upy3T.png Here's what I need: If a user checks a radio button with a ...

Error: Module '/node_modules/.vite/deps/react-pro-sidebar.js?v=913080ef' does not export 'ProSidebar' as requested

Using the pro-side-bar library in React is causing an issue for me. When I run the code, the console shows the following error using the dev tools: Uncaught SyntaxError: The requested module '/node_modules/.vite/deps/react-pro-sidebar.js?v=913080ef& ...

Creating a regular expression for validating phone numbers with a designated country code

Trying to create a regular expression for a specific country code and phone number format. const regexCountryCode = new RegExp('^\\+(48)[0-9]{9}$'); console.log( regexCountryCode.test(String(+48124223232)) ); My goal is to va ...

Sign up for the observable, retrieve the asynchronous mapped outcome with input from the dialog, and then utilize the outcome from the map

Currently, I am utilizing an API-service that delivers an Observable containing an array of elements. apiMethod(input: Input): Observable<ResultElement[]> Typically, I have been selecting the first element from the array, subscribing to it, and the ...

What is the best way to switch to a different screen in a React Native application?

I've recently dived into the world of React Native and embarked on a new project. The initial screen that greets users upon launching the app is the "welcome screen," complete with a prominent 'continue' button. Ideally, clicking this button ...

What is the method for configuring the <title> of a client component in Next 13?

Currently, I am in the process of transitioning my Next 12 app to Next 13 along with its updated /app directory. Within this transition, I have a <LoginPage> component (located at /login) that requires the use of hooks for managing form data. To acc ...

The initial invocation of OidcSecurityService.getAccessToken() returns null as the token

Our internal application requires all users to be authenticated and authorized, including for the home page. To achieve this, we use an HttpInterceptor to add a bearer token to our API requests. Initially, when rendering the first set of data with the fir ...

Exploring nested JSON objects within an array using ngFor directive

My application uses Angular 6 and Firebase. I am trying to showcase a list of all appointments. Below is my approach: service.ts getRDV() { this.rdvList = this.firebase.list('/rdv'); return this.rdvList; } Model: export class RDV { key: ...

Avoid the occurrence of the parent's event on the child node

Attempting to make changes to an existing table created in react, the table is comprised of rows and cells structured as follows: <Table> <Row onClick={rowClickHandler}> <Cell onCLick={cellClickHandler} /> <Cell /> ...

Firebase Remote Config integration with Next.js

I encountered an issue while trying to incorporate Google's Firebase Remote config into my Next.js app. Instead of following Firebase's documentation and directly inserting the functions into my component's code block, like this: ...

Error: n.indexOf function is not defined - Issue with Firebase

After integrating Stripe into Firebase, I encountered an issue where a specific line of code is supposed to execute whenever a user upgrades their plan. This code should create checkout sessions in the users' collection, but it throws an error instead ...

"Encountering a 500 error on Chrome and Internet Explorer while trying to sign

I am currently working on an ASP.NET Core application that handles identity management through Azure AD B2C using the ASP.Net Core OpenID Connect. The front end is developed using AngularJS 2 with TypeScript. In my Logout function, the user is redirected t ...

I'm having trouble with the DaisyUi navbar; it's not opening the dropdown menu as smoothly as it does on the DaisyUi website when using

Currently, I am experimenting with daisy and tailwind in my project without making many changes to the JavaScript. However, I am facing an issue where it does not behave the same as on the daisyUI website. When I click on 'Parent' in my script, t ...

Can PurgeCSS be implemented with Next.js and module.scss files?

Is there a way to use purgeCSS with component level .scss files (filename.module.scss) in order to remove unused CSS? The hashed classnames make it tricky, especially in a next.js app that heavily relies on module.scss files for styling. This thread here ...

Guide on creating a detailed list of categories mapped to specific classes that all adhere to a common generic standard

Most TypeScript factory patterns I've encountered rely on a named mapping between a name and the Class type. A basic implementation example: const myMap = { classOne: ExampleClass, classTwo: AnotherClass } (k: string) => { return new myMap[k] } ...

What is the best way to change an array element into a string in TypeScript?

Within my Angular 2 component, I am utilizing an array named fieldlist which is populated by data retrieved from an http.get request. The array is declared as follows: fieldlist: string[] = []; I populate this array by iterating through the JSON response ...

Integrate the retrieved information into a new object and then proceed to export it

Hey there! I'm looking to retrieve data from an API and merge it with some existing data in an array of objects. The goal is to then export this combined data for use in another part of my web application. Check out the following code example: //expo ...

How to use hooks in NETXJS to pass data from a page to a component

Hey there, how are you doing? I am currently working on a project using Next.js and styled components. I am trying to change a string using props in my layout component, where the main content is dynamic per page. Page 'prueba.js' import React f ...

Having trouble with Nextjs not rendering as expected and displaying a "Warning Prop `style` did not match" error when using inline styles?

Issue Description I'm encountering a problem with my nextjs application. I need to apply different styles/classNames to certain components based on whether they are rendered on the client-side or server-side. Below is a simplified demonstration code ...