Error: NEXT_REDIRECT #9389
-
using next-auth": "^5.0.0-beta.4. The problem is the error "NEXT_REDIRECT" it occurs every time I try to wrap methods singIn, singOut in a try catch block, in this case login happens, data is written to the session, but redirection does not happen. After refreshing the page my middleware redirects normally, and the data is there, I try to exit through signOut which is wrapped in try catch, again the exit occurs normally, but no redirection occurs. CODEauth.jsexport const {
signIn,
signOut,
auth
} = NextAuth({
...authConfig,
providers: [
CredentialsProvider({
async authorize(credentials) {
try {
const user = {username: 'test', email: 'test'}
return user;
} catch (err) {
console.log('authorize error:', err)
return null;
}
},
}),
],
callbacks: {
async jwt({ token, user }) {
if (user) {
token.username = user.username;
token.img = user.img;
}
return token;
},
async session({ session, token }) {
if (token) {
session.user.username = token.username;
session.user.img = token.img;
}
return session;
},
},
}); authconfig.jsexport const authConfig = {
providers: [],
pages: {
signIn: "/login",
},
callbacks: {
async authorized({ auth, request }) {
console.log('============================================');
const isLoggedIn = auth?.user;
const isOnDashboard = request.nextUrl.pathname.startsWith("/dashboard");
console.log('auth:', auth, 'isLoggedIn', isLoggedIn, 'isOnDashboard', isOnDashboard)
if (isOnDashboard) {
if (isLoggedIn) return true;
return false;
} else if (isLoggedIn) {
return Response.redirect(new URL("/dashboard", request.nextUrl));
}
return true;
},
},
}; This is the basic structure, here's how I try to use it in LoginForm import styles from "./loginForm.module.css";
import { signIn } from "@/app/auth";
const LoginForm = () => {
return (
<form action={async (formData) => {
"use server"
try {
await signIn("credentials", formData);
}
catch (e) {
console.log(e);
}
}} className={styles.form}>
<h1>Login</h1>
<input type="text" placeholder="username" name="username" />
<input type="password" placeholder="password" name="password" />
<button>Login</button>
</form>
);
};
export default LoginForm; And in this case if I use try catch I get an error. Full errorError: NEXT_REDIRECT
at getRedirectError (webpack-internal:///(rsc)/./node_modules/next/dist/client/components/redirect.js:44:19)
at redirect (webpack-internal:///(rsc)/./node_modules/next/dist/client/components/redirect.js:54:11)
at signIn (webpack-internal:///(rsc)/./node_modules/next-auth/lib/actions.js:62:89)
at async $$ACTION_1 (webpack-internal:///(rsc)/./app/ui/login/loginForm/loginForm.jsx:69:9)
at async D:\Person\Edvard\Desktop\nextadmin\node_modules\next\dist\compiled\next-server\app-page.runtime.dev.js:38:489
at async tX (D:\Person\Edvard\Desktop\nextadmin\node_modules\next\dist\compiled\next-server\app-page.runtime.dev.js:37:5313)
at async rl (D:\Person\Edvard\Desktop\nextadmin\node_modules\next\dist\compiled\next-server\app-page.runtime.dev.js:38:23339)
at async doRender (D:\Person\Edvard\Desktop\nextadmin\node_modules\next\dist\server\base-server.js:1406:30)
at async cacheEntry.responseCache.get.routeKind (D:\Person\Edvard\Desktop\nextadmin\node_modules\next\dist\server\base-server.js:1567:28)
at async DevServer.renderToResponseWithComponentsImpl (D:\Person\Edvard\Desktop\nextadmin\node_modules\next\dist\server\base-server.js:1475:28)
at async DevServer.renderPageComponent (D:\Person\Edvard\Desktop\nextadmin\node_modules\next\dist\server\base-server.js:1852:24)
at async DevServer.renderToResponseImpl (D:\Person\Edvard\Desktop\nextadmin\node_modules\next\dist\server\base-server.js:1890:32)
at async DevServer.pipeImpl (D:\Person\Edvard\Desktop\nextadmin\node_modules\next\dist\server\base-server.js:902:25)
at async NextNodeServer.handleCatchallRenderRequest (D:\Person\Edvard\Desktop\nextadmin\node_modules\next\dist\server\next-server.js:266:17)
at async DevServer.handleRequestImpl (D:\Person\Edvard\Desktop\nextadmin\node_modules\next\dist\server\base-server.js:798:17) {
digest: 'NEXT_REDIRECT;replace;http://localhost:3000/login?callbackUrl=http%3A%2F%2Flocalhost%3A3000%2Fdashboard;false',
mutableCookies: p {
_parsed: Map(6) {
'next-auth.csrf-token' => [Object],
'authjs.csrf-token' => [Object],
'next-auth.callback-url' => [Object],
'next-auth.session-token' => [Object],
'authjs.callback-url' => [Object],
'authjs.session-token' => [Object]
},
_headers: HeadersList {
cookies: [Array],
[Symbol(headers map)]: [Map],
[Symbol(headers map sorted)]: null
}
}
} |
Beta Was this translation helpful? Give feedback.
Replies: 10 comments 19 replies
-
I noticed that the catch block in your form's action async function is currently logging the error to the console but not re-throwing it. This could be causing the issue you're encountering. Try to add "throw e" in catch.
|
Beta Was this translation helpful? Give feedback.
-
This is crazy. What's the point of having the framework + auth library when such simple stuff don't work built-in? |
Beta Was this translation helpful? Give feedback.
-
This library is literally is a garbage. |
Beta Was this translation helpful? Give feedback.
-
In my case I removed the try catch and let me redirect to /* eslint-disable import/no-extraneous-dependencies */
'use server';
import { signIn } from '@/auth';
export async function sendUhOidAction(
prevState: {
message: string;
},
email: string,
) {
// try {
await signIn('credentials', {
email,
redirectTo: '/test',
});
// return undefined;
// } catch (error) {
// console.log({ error });
// if (error instanceof Error) {
// const { type, cause } = error as AuthError;
// switch (type) {
// case 'CredentialsSignin':
// return 'Invalid credentials.';
// case 'CallbackRouteError':
// return cause?.err?.toString();
// default:
// return 'Something went wrong.';
// }
// }
// throw error;
// }
} |
Beta Was this translation helpful? Give feedback.
-
After hours of struggling I found a solution: |
Beta Was this translation helpful? Give feedback.
-
Hi, still failing for me import { Button, Input, Label } from '$ui'
import { SigninHeader } from '$/app/signin/layout'
import { signIn } from '$/auth'
import { PageProps } from '$/lib/types'
import { isRedirectError } from 'next/dist/client/components/redirect'
export default async function SignInPage(props: PageProps<'', 'callbackUrl'>) {
const callbackUrl = String(props.searchParams.callbackUrl ?? '/')
return (
<>
<SigninHeader
title='Access your books'
description='Enter your email below to see your books.'
/>
<form
action={async (formData) => {
'use server'
try {
await signIn('nodemailer', {
callbackUrl,
email: formData.get('email')?.toString()!,
})
} catch (error) {
if (isRedirectError(error)) {
console.log('FUCK!: ', error)
throw error
}
}
}}
>
<div className='grid gap-2'>
<div className='grid gap-1'>
<Label className='sr-only' htmlFor='email'>
Email
</Label>
<Input
autoFocus
required
id='email'
name='email'
placeholder='Your email address'
type='email'
autoCapitalize='none'
autoComplete='email'
autoCorrect='off'
/>
</div>
<Button>Sign In with Email</Button>
</div>
</form>
</>
)
}
DebuggingDebugging the code I think https://github.com/nextauthjs/next-auth/blob/main/packages/next-auth/src/lib/actions.ts#L76 That gets the URL from If I put a log in [auth][debug]: Error in Auth "Redirecting to http://localhost:3003/api/auth/error?error=Configuration and isRedirect=false" But then here if (shouldRedirect) return redirect(res.redirect!)
Which makes sense with what I see in the logs The docs for custom signin page could be improved covering error handling |
Beta Was this translation helpful? Give feedback.
-
I can confirm. If I hack this line with a hardcoded URL it redirects to the error page - if (shouldRedirect) return redirect(res.redirect!)
+ if (shouldRedirect) {
+ return redirect('http://localhost:3003/api/auth/error?error=Configuration');
+ } Now the question is why |
Beta Was this translation helpful? Give feedback.
-
I made a PR that I think it fix at least some cases when the error is of type |
Beta Was this translation helpful? Give feedback.
-
|
Beta Was this translation helpful? Give feedback.
-
I came across this thread because I encountered what I initially thought was a similar issue when implementing credentials flow. This is my first time working with NextAuth and it turns out I missed the part in the doc that specifies that you need to explicitly set your session strategy to jwt: session: {
strategy: 'jwt'
}, Hopefully this will help someone else who runs into the same problem! |
Beta Was this translation helpful? Give feedback.
EDIT - I figured out a solution, add the following code to the catch block in the authenticate action:
I am slightly confused why it's necessary to throw e; when I want to be able to send messages back to the client:
// action.ts