Next.js Discord

Discord Forum

Weird Middleware error?

Answered
D34dlyK1ss posted this in #help-forum
Open in Discord
I don't remember the change I made before this, but I'm getting a weird error every time my web app starts. I think it has to do with middleware, because when I remove it. this doesn't happen, and I get my Page error as normal
 Error [TypeError]: Cannot read properties of undefined (reading 'replace')
    at <unknown> (webpack-internal:///(middleware)/./node_modules/jsdom/lib/jsdom/living/helpers/http-request.js:7)
    at eval (webpack-internal:///(middleware)/./node_modules/jsdom/lib/jsdom/living/helpers/http-request.js:7:29)
    at (middleware)/./node_modules/jsdom/lib/jsdom/living/helpers/http-request.js (file://C:\Users\D34dlyK1ss\Documents\Code\who-is-it\.next\server\middleware.js:3876:1)
    at __webpack_require__ (file://C:\Users\D34dlyK1ss\Documents\Code\who-is-it\.next\server\edge-runtime-webpack.js:37:33)
    at fn (file://C:\Users\D34dlyK1ss\Documents\Code\who-is-it\.next\server\edge-runtime-webpack.js:285:21)
    at eval (webpack-internal:///(middleware)/./node_modules/jsdom/lib/jsdom/living/xhr/xhr-utils.js:12:17)
    at (middleware)/./node_modules/jsdom/lib/jsdom/living/xhr/xhr-utils.js (file://C:\Users\D34dlyK1ss\Documents\Code\who-is-it\.next\server\middleware.js:5790:1)
    at __webpack_require__ (file://C:\Users\D34dlyK1ss\Documents\Code\who-is-it\.next\server\edge-runtime-webpack.js:37:33)
    at fn (file://C:\Users\D34dlyK1ss\Documents\Code\who-is-it\.next\server\edge-runtime-webpack.js:285:21)
    at eval (webpack-internal:///(middleware)/./node_modules/jsdom/lib/jsdom/living/xhr/XMLHttpRequest-impl.js:11:18)
    at (middleware)/./node_modules/jsdom/lib/jsdom/living/xhr/XMLHttpRequest-impl.js (file://C:\Users\D34dlyK1ss\Documents\Code\who-is-it\.next\server\middleware.js:5746:1)
Answered by D34dlyK1ss
import { NextResponse } from "next/server";

export async function middleware(request) {
    const session = request.cookies.get("session")?.value;
    const response = NextResponse.next();

    if (session && !request.nextUrl.pathname === "/") {
        response.cookies.set({
            name: "session",
            value: session,
            httpOnly: true,
            expires: new Date(Date.now() + 30 * 60 * 1000),
            secure: true
        });

        NextResponse.redirect(new URL("/", request.url));
        return response;
    }

    if (!session && !request.nextUrl.pathname.startsWith("/login")) {
        NextResponse.redirect(new URL("/login", request.url));
        return response;
    }
}

export const config = {
    matcher: ["/((?!api|_next/static|_next/image|favicon.ico).*)"]
};
View full answer

209 Replies

this is the same error but on the browser
this is what happens if rename/delete middleware. shows a bug I intend to fix
 ⨯ app\page.jsx (11:83) @ user
 ⨯ TypeError: Cannot read properties of null (reading 'user')
    at Page (./app/page.jsx:24:73)
digest: "3884015737"
   9 |                  <span className="spanProfile menu clickable">
  10 |                          <div className="divPicture">
> 11 |                                  <img className="imgPicture menu" src={`https://gravatar.com/avatar/${session.user.email}?d=identicon`} />
     |                                                                                                               ^
  12 |                          </div>
  13 |                          <p className="pUsername menu">
  14 |                                  <b>{session.user.username}</b>
@D34dlyK1ss I don't remember the change I made before this, but I'm getting a weird error every time my web app starts. I think it has to do with middleware, because when I remove it. this doesn't happen, and I get my Page error as normal error Error [TypeError]: Cannot read properties of undefined (reading 'replace') at <unknown> (webpack-internal:///(middleware)/./node_modules/jsdom/lib/jsdom/living/helpers/http-request.js:7) at eval (webpack-internal:///(middleware)/./node_modules/jsdom/lib/jsdom/living/helpers/http-request.js:7:29) at (middleware)/./node_modules/jsdom/lib/jsdom/living/helpers/http-request.js (file://C:\Users\D34dlyK1ss\Documents\Code\who-is-it\.next\server\middleware.js:3876:1) at __webpack_require__ (file://C:\Users\D34dlyK1ss\Documents\Code\who-is-it\.next\server\edge-runtime-webpack.js:37:33) at fn (file://C:\Users\D34dlyK1ss\Documents\Code\who-is-it\.next\server\edge-runtime-webpack.js:285:21) at eval (webpack-internal:///(middleware)/./node_modules/jsdom/lib/jsdom/living/xhr/xhr-utils.js:12:17) at (middleware)/./node_modules/jsdom/lib/jsdom/living/xhr/xhr-utils.js (file://C:\Users\D34dlyK1ss\Documents\Code\who-is-it\.next\server\middleware.js:5790:1) at __webpack_require__ (file://C:\Users\D34dlyK1ss\Documents\Code\who-is-it\.next\server\edge-runtime-webpack.js:37:33) at fn (file://C:\Users\D34dlyK1ss\Documents\Code\who-is-it\.next\server\edge-runtime-webpack.js:285:21) at eval (webpack-internal:///(middleware)/./node_modules/jsdom/lib/jsdom/living/xhr/XMLHttpRequest-impl.js:11:18) at (middleware)/./node_modules/jsdom/lib/jsdom/living/xhr/XMLHttpRequest-impl.js (file://C:\Users\D34dlyK1ss\Documents\Code\who-is-it\.next\server\middleware.js:5746:1)
check if object is defined before trying to modify it
this is my middlware.js
import { updateSession } from "@/api/userController.js";

export async function middleware(request) {
    await updateSession(request);

    const session = request.cookies.get("session")?.value;

    if (session && !request.nextUrl.pathname === "/") {
        return Response.redirect(new URL("/", request.url));
    }

    if (!session && !request.nextUrl.pathname.startsWith("/login")) {
        return Response.redirect(new URL("/login", request.url));
    }
}

export const config = {
    matcher: ["/((?!api|_next/static|_next/image|favicon.ico).*)"]
};
@D34dlyK1ss which object?
your user
let me show you
export async function updateSession(request) {
    const session = request.cookies.get("session")?.value;
    if (!session) return;

    // Refresh the session so it doesn't expire
    const parsed = await decrypt(session);
    parsed.expires = new Date(Date.now() + 30 * 60 * 1000);

    const res = NextResponse.next();
    res.cookies.set({
        name: "session",
        value: await encrypt(parsed),
        httpOnly: true,
        expires: parsed.expires,
        secure: true
    });

    return res;
}
wait
I know the 2nd error
my problem is the middleware one
I know how to fix my user error
I had the theory middleware freaks out when I get an error
so it ends up masking the actual error with another
but it's not the case
u trying to read a cookie that is not yet defined
so I return empty
your "session" cookie can only be set afer middleware returns
your updateSession should return the cookie
and use that to check if your session is not null
and set the cookie on successful response
let's take a step back
@gin my middleware is like this now. not running any code
my main page, the same
so there would be no errors atm. right?
with middleware disabled, I get my main page empty as intended:
enabling middlware, this happens
focus on this error
not the other
the other I can fix alone
I already tried deleting .next/, reinstalling node_modules. nothing worked
middleware's fiddling with something on Next.JS I can't understand what
look
make ur update Session take the cookieValue as param and make it only return true and false.
based on that u can redirect the user
if its true and your session is valid u set the cookie in your response
ok I figured another correct answer
my bad
commenting the import
import { updateSession } from "@/api/userController.js";
gets rid of the error
even if I don't use updateSession anywhere
so in the end middleware is reading the code from updateSession anyway, that's why I was so confused
I gotta fix it first
but I didn't understand what was actually happening
I thought my error wouldn't affect middleware this way
ur confusing me, how can your middleware use a function that is not imported
can u do my steps i told u?
or is your issue fixed
😂
remember when I said middleware is not executing any code?
I don't have updateSession running anywhere
I swear
so I asked myself why would it be the problem
any problems within updateSession can't mess with the app if it's not being used
BUT
IF I COMMENT THE IMPORT
ISSUE RESOLVED
😂
alr
from this
to this
like wtf 😂
why was it triggering an error?
does Next.js read/test the code on imports?
no
or does middleware just trigger the code inside that import anyway?
no it doesnt
so can you understand the fact that makes no sense getting an error from updateSession if it's not being used anywhere else?
doesn't matter
let me fix the actual issue
thanks btw
oh btw
this middlware code, updateSession etc. all come from that session video from Lee
I followed everything
all of a sudden I change the updateSession from one file I ended up deleting to userController.js
then this bug started triggering
this are my imports in userController.js

import { decrypt, encrypt, loginToConsole, logoutToConsole, newId } from "@/lib.js";
import { cookies } from "next/headers";
import database from "@/api/database.js";
import JSDOM from "jsdom";
import { NextResponse } from "next/server";
import nodemailer from "nodemailer";
import { readFileSync } from "fs";
u followed everything 1to1?
I even copied his code from GitHub XDDD
export async function updateSession(request) {
    const session = request.cookies.get("session")?.value;
    if (!session) return;

    // Refresh the session so it doesn't expire
    const parsed = await decrypt(session);
    parsed.expires = new Date(Date.now() + 30 * 60 * 1000);

    const res = NextResponse.next();
    res.cookies.set({
        name: "session",
        value: await encrypt(parsed),
        httpOnly: true,
        expires: parsed.expires,
        secure: true
    });

    return res;
}
u are returning the next response within the function
i wouldnt do that
oh
that what Lee does
bad
also u are not using the response
u just calling the function
oof wait
I may have done some doodoo
my brain ain't braining after so much pressure I've been putting on myself for this project
Lee's updateSession
isn't this supposed to go like this?
first thats typescript, u are using js
I know
make ure updateSession take the cookie as value
do ur stuff
and return the encrypted string back
or undefined if session is invalid
use the returned value to send user to login or to your page
if value is not undefined and your session is valid, set the your cookie in your response
and return that response
@gin make ure updateSession take the cookie as value
you're saying the incoming request is in another type?
other than the suposed NextRequest?
since JS doesn't let me force anything, makes harder to find where I actually miss
make ur function take the cookie value as string
do not use the request and response object outside of the middleware
it will slow down the execution
ok
i can give u the correct solution if u want
sorry
don't spoonfeed 😅
ok, i told u the steps
I can get there
alr
mostly
this is what you meant right?
return parsed; in the end
forgot
get the session cookie in the middleware
and pass it to the updateSession
request.cookies.get("session")?.value
oh want me to get the cookie from there
yeah yeah
I see it now
I wonder if I should do the value validation inside updateSession or in middleware
probably middleware so I redirect
also need to reorder that const on middleware
it's out of place
remove this
set the cookie on your response
if session is not null
~yeppers
forgot I'm doing that already in middleware from request
jesus
I need to restart my brain, it's running on 1MHz
@D34dlyK1ss forgot I'm doing that already in middleware from request
u should use the response object to set the cookie
const response = NextResponse.next();
response.cookies.set("session")
like that
u can return the response if your cookie session is undefined
inside here
const response = NextResponse.next();

if (session) {
response.cookie.set("session")
return response // return response
}

return response
get it
should be this
but then
expires needs to be a different thing
I have to decrypt session first
that way encrypt will make sense then
cause at the moment I don't need to use it if I don't decrypt it first
or I just change things around and do this instead 😂
you need to set the cookie in your response
isn't that what I am doing in the last pic?
ah wait
nope
take a look at this
I am using Response instead of NextResponse
use NextResponse
check docs
yes I know I have to
was just clarifying to myself
import { decrypt } from "@/lib.js";
import { NextResponse } from "next/server";
import { updateSession } from "@/api/userController.js";

export async function middleware(request) {
    const session = request.cookies.get("session")?.value;
    const response = NextResponse.next();

    if (session && !request.nextUrl.pathname === "/") {
        response.cookies.set({
            name: "session",
            value: session,
            httpOnly: true,
            expires: await decrypt(session).expires,
            secure: true
        });

        return response.redirect(new URL("/", request.url));
    }

    if (!session && !request.nextUrl.pathname.startsWith("/login")) {
        return response.redirect(new URL("/login", request.url));
    }

    await updateSession(session);
}

export const config = {
    matcher: ["/((?!api|_next/static|_next/image|favicon.ico).*)"]
};
does response.redirect update it?
or do I really need to return Response first
u cant redirect if ur response is already NextResponse.next
I see
u can set the response dynamically
let response
rest you know
yeah
thanks
also, u will not need your updateSession functio anymore
u can remove that
yes
because I brought everything to middleware
instead of having it somewhere else
import { NextResponse } from "next/server";

export async function middleware(request) {
    const session = request.cookies.get("session")?.value;
    const response = NextResponse.next();

    if (session && !request.nextUrl.pathname === "/") {
        response.cookies.set({
            name: "session",
            value: session,
            httpOnly: true,
            expires: new Date(Date.now() + 30 * 60 * 1000),
            secure: true
        });

        NextResponse.redirect(new URL("/", request.url));
        return response;
    }

    if (!session && !request.nextUrl.pathname.startsWith("/login")) {
        NextResponse.redirect(new URL("/login", request.url));
        return response;
    }
}

export const config = {
    matcher: ["/((?!api|_next/static|_next/image|favicon.ico).*)"]
};
Answer
finally
everything fixed in this code
I had so much things messed up
oh, I was about to set the tag as solved
but there's no tag for that
nice glad it worked
yep thank you
it's my first time with Next
do this
@D34dlyK1ss it's my first time with Next
yeah i see
I had PHP in my bachelor's
its always confusing the first time
it was way easier but less "interactive"
it's not like I can't understand the concept
it's more like having it all settled
yeah u have to just learn it
since next has a huge ecosystem
and that's good
I had a look at those docs before, but things just went above my head anyway 😂
remember guys, take breaks from coding. it helps 👍🏻