Next.js Discord

Discord Forum

Mongoose + Middleware: Cannot read properties of undefined

Unanswered
Spectacled bear posted this in #help-forum
Open in Discord
Spectacled bearOP
Using Next.js 14 app router with mongoose, I encounter this error as soon as I import a server action into my middleware:
 ⨯ src\models\nachricht.ts (38:0) @ <unknown>
 ⨯ Cannot read properties of undefined (reading 'Message')
 36 | );
 37 |
> 38 | export default mongoose.models.Message || mongoose.model('Message', messageSchema)


The root of the issue seems to be that [middleware in Next.js is an edge runtime and DB connections aren't recommended in there](https://nextjs-forum.com/post/1142075909856305162#message-1142087679559860244).

Why isn't it possible to connect to a DB in Next.js middleware? And what's the alternative?

### (Temporary) solution
I've solved the problem temporarily by moving saveMessage() to a seperate file for server actions which establish database connection and use models.
But this is indeed only a temporary fix, because sooner or later the getUniqueCityNamesAndSlugs() action will also work with a database connection (instead of a JSON file).

1 Reply

Spectacled bearOP
## File Structure/Code during bug

src/models/nachricht.ts:
import mongoose from "mongoose";

const { Schema } = mongoose;

const messageSchema = new Schema(
    // ...
);

export default mongoose.models.Message || mongoose.model('Message', messageSchema)


src/lib/db.ts:
import mongoose from "mongoose";

const connect = async () => {
    if(mongoose.connections[0].readyState) {
        console.log('Mongoose already connected')
        return
    };

    try {
        console.log('MONGODB_URI', process.env.MONGODB_URI)
        await mongoose.connect(process.env.MONGODB_URI)
        console.log('Mongoose connected')
    } catch (error) {
        console.error('error:', error)
    }
}

export default connect;


src/app/actions.ts:
'use server'

import hpOrgDb from "@/lib/hpOrgDb.json"
import connect from "@/lib/db"
import nachricht from "@/models/nachricht"

// ...

export async function getUniqueCityNamesAndSlugs(){
    // ...getting a list of all cities in the DB (currently just using a JSON file)
}

export async function saveMessage(prevState, formData){
    await connect()
    try {
        await nachricht.create({
            // formData
        })
    } catch (error) {
        // ...error catching
        return newState
    }

    return newState
}


src/middleware.js:
import { NextResponse } from 'next/server'
import { getUniqueCityNamesAndSlugs } from '@/app/actions'  // <=== ISSUE HERE!?

export async function middleware(request) {    
    if (request.nextUrl.pathname.includes("/doc-")) {
        // ...
        const uniqueCityNamesAndSlugs = await getUniqueCityNamesAndSlugs()

        // ...
        return NextResponse.rewrite(new URL(`/doc/${cityName}`, request.url))
    }
}