Uncaught SyntaxError: expected expression, got '<' while using Next.js middleware
Asked Answered
W

5

12

I'm using Next.js middleware to redirect to the login page if there's no available token using Spotify's API,

My middleware looks like this:

import { getToken } from "next-auth/jwt";
import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";

export async function middleware(req: NextRequest) {
  //   const token = await getToken({ req, secret: process.env.JWT_SECRET });
  const token = await getToken({ req, secret: process.env.NEXTAUTH_SECRET });
  const { pathname, origin } = req.nextUrl;
  if (pathname.includes("/api/auth") || token) {
    return NextResponse.next();
  }
  //   console.log(origin);
  // console.log(token);

  if (!token && pathname != "/login") {
    return NextResponse.redirect(new URL(`${origin}/login`));
  }
}

If I comment out this section:

  if (!token && pathname != "/login") {
    return NextResponse.redirect(`${origin}/login`);
  }

I stop getting the error but obviously, I need this line to redirect if there's no token, I tried to check for any syntax errors or any mistakes but I can't seem to find it myself, any help?

the errors i'm getting are these :

Uncaught SyntaxError: expected expression, got '<'
react-refresh.js:1
Uncaught SyntaxError: expected expression, got '<'
webpack.js:1
Uncaught SyntaxError: expected expression, got '<'
main.js:1
Uncaught SyntaxError: expected expression, got '<'
_app.js:1
Uncaught SyntaxError: expected expression, got '<'
login.js:1
Uncaught SyntaxError: expected expression, got '<'
_buildManifest.js:1
Uncaught SyntaxError: expected expression, got '<'
Weka answered 4/8, 2022 at 0:28 Comment(5)
I noticed one difference between your code and Next.js docs: import type { NextRequest } from 'next/server'. You don't have type in there. No idea if this has anything to do with the issue.Hypertrophy
@IrfanullahJan oh you're right , I changed my code to what you mentioned and i seem to still to be getting the same error , good catch thoughWeka
Can you wrap the redirect URL with new URL() because this is how they do it in the docs.Hypertrophy
@IrfanullahJan you're right , I tried doing so and changed my code in my original post , sadly the same error after stopping and running the app again tooWeka
Oh okay, could you please add the error call stack to the question above? I hope that will help someone spot the reason.Hypertrophy
H
4

Looks like this is a recent issue with Next.js and hopefully, they will fix it.

Please see: https://github.com/vercel/next.js/issues/38934#issuecomment-1193083803 which seems to be the same issue as the one you are facing.

Meanwhile, please try downgrading Next.js and React.js to see if that helps.

Hypertrophy answered 4/8, 2022 at 1:2 Comment(5)
downgrading it seems to work , thanks :)Weka
@MohamedNabil which version of Next.js did you downgrade to?Antiphon
@Antiphon I don't really remember , i've tried looking around for my project and couldn't find it , sorry :(Weka
@MohamedNabil You can't find it in package.json?Antiphon
@Antiphon not really , I believe I just downgraded to the version before the one I was usingWeka
A
21

the problem is Next.js is making some request to /_next/* and you redirect request to the login page, those requests are needed and but are never finished.

You need to avoid redirect any requests made to /_next/*

export const config = {
  matcher: [
    '/((?!_next|api/auth).*)(.+)'
  ],
}
Antiphon answered 30/9, 2022 at 3:47 Comment(1)
or ``` if(/^(?!\/(_next|api)\/).*$/.test(request.url)) //can rewrite ```Claustrophobia
H
13

I had the same issue, the solution that worked for me was

export const config = {
matcher: "/",
};

Add this code to your middleware.ts file and this would solve the issue :)

Hedonic answered 29/8, 2022 at 23:48 Comment(0)
A
6

I had the same issue, and this pretty much solved the problem for me:

export const config = {
   matcher: '/',
};

I think this is a bug that comes with the latest Next JS release, the solution above helps. Also downgrading to another version of Next JS and React should solve the issue.

Arlynearlynne answered 11/10, 2022 at 14:32 Comment(0)
H
4

Looks like this is a recent issue with Next.js and hopefully, they will fix it.

Please see: https://github.com/vercel/next.js/issues/38934#issuecomment-1193083803 which seems to be the same issue as the one you are facing.

Meanwhile, please try downgrading Next.js and React.js to see if that helps.

Hypertrophy answered 4/8, 2022 at 1:2 Comment(5)
downgrading it seems to work , thanks :)Weka
@MohamedNabil which version of Next.js did you downgrade to?Antiphon
@Antiphon I don't really remember , i've tried looking around for my project and couldn't find it , sorry :(Weka
@MohamedNabil You can't find it in package.json?Antiphon
@Antiphon not really , I believe I just downgraded to the version before the one I was usingWeka
S
0

Obviously, this is not ideal but is a temporary fix. So for some reason when files that start with /_next get requested and you have a redirect to login it will send the redirected file to the /_next file. As a temporary fix, you need to filter out this files request. I am using next.js 12.3.1 and this worked for me.

In this case, if the user session does not have the user property it will redirect the user to the login screen without error.

    if (
        !session.hasOwnProperty("user") &&
        url != '/_next/static/development/_ssgManifest.js' &&
        url != '/_next/static/development/_buildManifest.js' &&
        url != '/_next/static/chunks/pages/_app.js' &&
        url != '/_next/static/chunks/react-refresh.js' &&
        url != '/_next/static/chunks/main.js' &&
        url != '/_next/static/chunks/webpack.js' &&
        url != '/_next/static/chunks/pages/login.js' &&
        url != '/manifest.json'
    ) {
        
        return NextResponse.redirect(new URL('/login', req.url))
      
    }

Complete middleware file

import { NextResponse } from "next/server"
import type { NextRequest } from "next/server";
import { getIronSession } from "iron-session/edge";

export async function middleware(req: NextRequest) {
    const url = req.nextUrl.pathname;    

    if (url.startsWith('/login') || url.startsWith('/api/login')) {        
        return NextResponse.next()
    }

    const res = NextResponse.next();
    const session = await getIronSession(req, res, {
        password: process.env.SECRET_COOKIE_PASSWORD,
        cookieName: "cookie"
    });

    // User session does not exist or it has expired
    if (
        !session.hasOwnProperty("user") &&
        url != '/_next/static/development/_ssgManifest.js' &&
        url != '/_next/static/development/_buildManifest.js' &&
        url != '/_next/static/chunks/pages/_app.js' &&
        url != '/_next/static/chunks/react-refresh.js' &&
        url != '/_next/static/chunks/main.js' &&
        url != '/_next/static/chunks/webpack.js' &&
        url != '/_next/static/chunks/pages/login.js' &&
        url != '/manifest.json'
    ) {        
        return NextResponse.redirect(new URL('/login', req.url))
    }

    return NextResponse.next()
}

Hope next js team fix this issue

Scopas answered 27/9, 2022 at 18:59 Comment(1)
why not just do url.includes('_next')?Antiphon

© 2022 - 2024 — McMap. All rights reserved.