Next.js Discord

Discord Forum

error TypeError: Cannot read properties of undefined (reading 'headers')

Answered
Standard Chinchilla posted this in #help-forum
Open in Discord
Avatar
Standard ChinchillaOP
Keeps on returning this when hitting this endpoint
import { prisma } from '../../../lib/prisma'
export async function POST(request: Request) {
  const res:  = await request.json()
  const userExists = await prisma.user.findUnique({
    where: {
      email: res.email,
    },
  })
}

77 Replies

Avatar
are you sure this code is correct? it says res: = await request.json()
Avatar
Standard ChinchillaOP
yea I mean i put the type now
import { hash } from 'bcrypt'
import { prisma } from '../../../lib/prisma'
import { CreateUserDto } from '../../../types'

export async function POST(request: Request) {
  const res: CreateUserDto = await request.json()
  const userExists = await prisma.user.findUnique({
    where: {
      email: res.email,
    },
  })
  if (!userExists) {
    const hashedPassword = await hash(res.password, 10)
    const user = await prisma.user.create({
      data: { email: res.email, name: res.name, password: hashedPassword },
    })
    delete user.password
    return user
  }
}
Avatar
and what is the error
Avatar
Standard ChinchillaOP
error TypeError: Cannot read properties of undefined (reading 'headers')
Avatar
i dont think ure supposed to return user
you need to return NextResponse
so if you're returning json object its return NextResponse.json(...data...)
or if its just a status its return new NextResponse(undefined, {status: 200})
Avatar
Standard ChinchillaOP
I mean not like that yes
Avatar
in what line did this error occur?
Avatar
Standard ChinchillaOP
dk
its giving webpack stuff
Avatar
...
try sending the whole error log
Avatar
Standard ChinchillaOP
thats it
Image
thats it
happens as soon as I hit the endpoint
export async function POST(request: Request) {
  const res: CreateUserDto = await request.json()
  const userExists = await prisma.user.findUnique({
    where: {
      email: res.email,
    },
  })
  if (!userExists) {
    const hashedPassword = await hash(res.password, 10)
    const user = await prisma.user.create({
      data: { email: res.email, name: res.name, password: hashedPassword },
    })

    //@ts-ignore
    delete user.password
    return NextResponse.json(user)
  } else {
    console.log(userExists)
    //@ts-ignore
    delete userExists.password

    NextResponse.json(userExists)
  }
}
sometimes it sends sometimes it doesn't
Avatar
this smells like a nextjs bug icl
does a very minimal endpoint work?
export async function POST(request: Request) {
  const json = await request.json();
  console.log(json);
  return NextResponse.json({});
}
Avatar
Standard ChinchillaOP
export async function GET() {
  console.log('GET /api/whop')
}
this doesn't
import { NextResponse } from 'next/server'

export async function POST(request: Request) {
  const json = await request.json()
  console.log(json)
  return NextResponse.json({})
}
this des
Avatar
wdym by doesn't and does?
both of these should work by the way
Avatar
Standard ChinchillaOP
returns the header error
Avatar
hmm interesting, this is 99% a nextjs bug now
Avatar
Standard ChinchillaOP
Image
seems to be
Avatar
100% a nextjs bug, i can reproduce
except... it's not? this throws the error
export async function POST(request: Request) {
  const json = await request.json();
  console.log(json);
}

but this doesn't
import { NextResponse } from "next/server";

export async function POST(request: Request) {
  const json = await request.json();
  console.log(json);
  return NextResponse.json({});
}
Avatar
Standard ChinchillaOP
yes ig when you don't return NextResponse
it happens
Avatar
should still be a bug, at least the error should've been clearer
Avatar
Standard ChinchillaOP
yes
Avatar
Answer
Avatar
Standard ChinchillaOP
@joulev
import { NextRequest, NextResponse } from 'next/server'
import { getServerSession } from 'next-auth'
import { prisma } from '../../../lib/prisma'
import { authOptions } from '../../authOptions'
import { redirect } from 'next/navigation'

export const dynamic = 'force-dynamic'
export async function GET(request: NextRequest, response: NextResponse) {
  const session = await getServerSession(authOptions)

  const url = new URL(request.url)
  const params = new URLSearchParams(url.search)
  const code = params.get('code')

  if (!session) {
    return NextResponse.json('No user in session', { status: 400 })
  }
  if (!code) {
    return NextResponse.json('Invalid Request')
  }

  try {
    const res = await (
      await fetch('https://data.whop.com/api/v3/oauth/token', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/x-www-form-urlencoded',
        },
        body: new URLSearchParams({
          grant_type: 'authorization_code',
          code: code,
          client_id: process.env.WHOP_CLIENT_ID,
          client_secret: process.env.WHOP_CLIENT_SECRET,
          redirect_uri: process.env.WHOP_REDIRECT_URI,
        }).toString(),
      })
    ).json()
    console.log(res.access_token)
    const userDetails = await (
      await fetch('https://api.whop.com/api/v2/me', {
        headers: {
          Authorization: `Bearer ${res.access_token}`,
        },
      })
    ).json()

    console.log(userDetails)
    await prisma.user.update({
      where: {
        email: session?.user.email!,
      },
      data: {
        whopId: userDetails.id,
      },
    })
    return redirect('/')
  } catch (e) {
    NextResponse.json({ errors: `${e}` }, { status: 400 })
  }
}
I have this now I am supposed to redirect how do i do that
it keeps on throwing that error
Avatar
try removing the return before redirect()
redirect() throws an error so doesnt need return
oh wait
redirect() throws an error, so your try-catch is catching it
you should not catch it
Avatar
Standard ChinchillaOP
didnt work
yes
hmm
Avatar
rewrite this to something like
try {
  // do other things
  } catch (e) {
    return NextResponse.json({ errors: `${e}` }, { status: 400 })
  }

// move redirect outside the try-catch
redirect('/')
if an error is caught, it will return that json
so redirect() is only run in the happy path
Avatar
Standard ChinchillaOP
kk
works thanks
Avatar
i will now close this thread, if you have a new question feel free to make a new one
Avatar
Standard ChinchillaOP
Okay no issues
Avatar
King Rail
Did you find a fix for the headers bug? I am experiencing the same thing.
Avatar
You have to return a response
Either return a Response or return a NextResponse
Avatar
King Rail
I do that
But for some reason still get the error
Avatar
well you need to show some code
with this much info i obviously cannot say anything
Avatar
King Rail
Of course not, was just wondering if you had heard something.
This is my code to return a response:
return NextResponse.json(
        { products: allProducts },
        {
          status: 200,
          headers: {
            "content-type": "application/json",
          },
        }
      )

allProducts is a array of stripe products.
I have tried playing around with different headers, removing them and so on.
Avatar
well, this works for me normally
Image
you must have a branch of code (e.g. an if/else, a try/catch) where the function terminates without a response
you can add the return type e.g. export function GET(): Response to ensure ts tells you where you forget to return the said response
Avatar
King Rail
Maybe, i am moving the api from an express js api to a nextjs api route. Everything is tested and works in the expressjs api, just need to change out the parts for the nextjs api.
How do you fetch the api?
Avatar
the fetch isn't important, you fetch it like any other apis
Avatar
King Rail
Okay
Well i am going to take a look at the route. Thank you!
You were right, i had a poorly writting try catch block. I am not sure why it worked fine in express tho. Thank you again!
Avatar
express most likely returns a default 200? response implicitly in that case
i would love nextjs to do that as well, but at the moment nextjs penalises all unreturned functions with this weird error so what to do
Avatar
King Rail
If the error was better explained it is probably fine that they do it this way. Makes people check their code through again i guess.
Avatar
yeah. i'm personally fine with both ways, but they absolutely need to get a better error message here at least