Mohamed Nabil
Mohamed Nabil

Reputation: 765

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

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 '<'

Upvotes: 15

Views: 9775

Answers (5)

Rongeegee
Rongeegee

Reputation: 1128

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).*)(.+)'
  ],
}

Upvotes: 24

Charles
Charles

Reputation: 173

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.

Upvotes: 6

leo
leo

Reputation: 59

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

Upvotes: 0

Jashandeep Singh
Jashandeep Singh

Reputation: 131

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 :)

Upvotes: 13

Irfanullah Jan
Irfanullah Jan

Reputation: 3892

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.

Upvotes: 4

Related Questions