0

I'm getting a 500 when trying to make a POST with my Next.js Application. I can't seem to figure out why.

I'm using Next.js, and MongoDB and the GET requests are working fine.

Posts.js

import clientPromise from "../../lib/mongodb";

export default async function handler(req, res) {
  const client = await clientPromise;
  const db = client.db("quick_ticker_db");

  switch (req.method) {
    case "POST":
      let bodyObject = JSON.parse(req.body);
      let myPost = await db.collection("posts").insertOne(bodyObject);

      res.json(myPost.ops[0]);
      break;
    case "GET":
      const allPosts = await db.collection("posts").find({}).toArray();

      res.json({ status: 200, data: allPosts });
      break;
  }
}

create.js


export default function CreateTicker() {
  // Handles the submit event on form submit.
  const handleSubmit = async (event) => {
    // Stop the form from submitting and refreshing the page.
    event.preventDefault()

    // Get data from the form.
    const data = { 
      ticker: event.target.ticker.value 
    }

    // Send the data to the server in JSON format.
    const JSONdata = JSON.stringify(data)

    // API endpoint where we send form data.
    const endpoint = '/api/posts'

    // Form the request for sending data to the server.
    const options = {
      // The method is POST because we are sending data.
      method: 'POST',
      // Tell the server we're sending JSON.
      headers: {
        'Content-Type': 'application/json',
      },
      // Body of the request is the JSON data we created above.
      body: JSONdata,
      encodeBodyAsJSON: true
    }

    // Send the form data to our forms API on Vercel and get a response.
    const response = await fetch(endpoint, options)

    // Get the response data from server as JSON.
    // If server returns the name submitted, that means the form works.
    const result = await response.json()

    result
  }

  return (
    // We pass the event to the handleSubmit() function on submit.
    <form onSubmit={handleSubmit}>
      <label htmlFor="ticker">Ticker</label>
      <input type="text" id="ticker" name="ticker" required />

      <button type="submit">Submit</button>
    </form>
  )
}

ERROR:

POST http://localhost:3000/api/posts 500 (Internal Server Error)
Uncaught (in promise) SyntaxError: Unexpected token '<', "<!DOCTYPE "... is not valid JSON

"message":"Unexpected number in JSON at position 1"

RESPONSE:

<!DOCTYPE html>
<html>

<head>
    <style data-next-hide-fouc="true">
        body {
            display: none
        }
    </style><noscript data-next-hide-fouc="true">
        <style>
            body {
                display: block
            }
        </style>
    </noscript>
    <meta charSet="utf-8" />
    <meta name="viewport" content="width=device-width" />
    <meta name="next-head-count" content="2" /><noscript data-n-css=""></noscript>
    <script defer="" nomodule="" src="/_next/static/chunks/polyfills.js?ts=1664669437061"></script>
    <script src="/_next/static/chunks/webpack.js?ts=1664669437061" defer=""></script>
    <script src="/_next/static/chunks/main.js?ts=1664669437061" defer=""></script>
    <script src="/_next/static/chunks/pages/_app.js?ts=1664669437061" defer=""></script>
    <script src="/_next/static/chunks/pages/_error.js?ts=1664669437061" defer=""></script>
    <script src="/_next/static/development/_buildManifest.js?ts=1664669437061" defer=""></script>
    <script src="/_next/static/development/_ssgManifest.js?ts=1664669437061" defer=""></script><noscript
        id="__next_css__DO_NOT_USE__"></noscript>
</head>

<body>
    <div id="__next" data-reactroot=""></div>
    <script src="/_next/static/chunks/react-refresh.js?ts=1664669437061"></script>
    <script id="__NEXT_DATA__" type="application/json">
        {"props":{"pageProps":{"statusCode":500}},"page":"/_error","query":{"__NEXT_PAGE":"/api/posts"},"buildId":"development","isFallback":false,"err":{"name":"SyntaxError","source":"server","message":"Unexpected number in JSON at position 1","stack":"SyntaxError: Unexpected number in JSON at position 1\n    at JSON.parse (\u003canonymous\u003e)\n    at handler (webpack-internal:///(api)/./pages/api/posts.js:12:35)\n    at processTicksAndRejections (internal/process/task_queues.js:95:5)\n    at async Object.apiResolver (/Users/Projects/Personal/quick-ticker-web/node_modules/next/dist/server/api-utils/node.js:366:9)\n    at async DevServer.runApi (/Users/Projects/Personal/quick-ticker-web/node_modules/next/dist/server/next-server.js:481:9)\n    at async Object.fn (/Users/Projects/Personal/quick-ticker-web/node_modules/next/dist/server/next-server.js:735:37)\n    at async Router.execute (/Users/Projects/Personal/quick-ticker-web/node_modules/next/dist/server/router.js:247:36)\n    at async DevServer.run (/Users/Projects/Personal/quick-ticker-web/node_modules/next/dist/server/base-server.js:347:29)\n    at async DevServer.run (/Users/Projects/Personal/quick-ticker-web/node_modules/next/dist/server/dev/next-dev-server.js:709:20)\n    at async DevServer.handleRequest (/Users/Projects/Personal/quick-ticker-web/node_modules/next/dist/server/base-server.js:285:20)"},"gip":true,"scriptLoader":[]}
    </script>
</body>

</html>

For the record GET requests are working just fine.

juliomalves
  • 42,130
  • 20
  • 150
  • 146
Bitwise
  • 8,021
  • 22
  • 70
  • 161
  • Clearly, the server is returning an HTML for a POST request. Can you provide the full response of it? – testing_22 Oct 02 '22 at 00:06
  • Yes! Updated just now – Bitwise Oct 02 '22 at 00:15
  • I'm not sure you want/need to use JSON.parse() when you've configured the client to send JSON data. Perhaps just need to configure express to use JSON as well, eg [this answer](https://stackoverflow.com/a/10007542/20042973)? – user20042973 Oct 02 '22 at 03:50
  • You shouldn't do `JSON.parse(req.body)`, just use `req.body` directly. Next.js will automatically parse the `body` of the request as JSON when you pass `application/json` in the `Content-Type` header. See [Next.js API Route mysteriously modifying JSON payload](https://stackoverflow.com/questions/70887907/next-js-api-route-mysteriously-modifying-json-payload). – juliomalves Oct 02 '22 at 17:22

1 Answers1

1

I think that is because your post logic throwing error:

  let bodyObject = JSON.parse(req.body);
  let myPost = await db.collection("posts").insertOne(bodyObject);

run this code in try/catch block.

your code is not reaching res.json(myPost.ops[0])

Yilmaz
  • 35,338
  • 10
  • 157
  • 202
  • I think you are right about the section of the code that is throwing the exception, and having proper error handling is generally good advice. However, I don't think this answer solves the fundamental problem. OP is clearly expecting the received object to be JSON so that it can be processed and stored. So I think the question is really about why the body of the POST request that's being sent by the front end is not being successfully parsed as JSON – user20042973 Oct 02 '22 at 03:08
  • @user20042973 In order to solve the problem, I need to have the minimal reproducible example so I could debug it. – Yilmaz Oct 02 '22 at 03:16
  • 1
    I don't disagree, but you should tell OP not me :-) – user20042973 Oct 02 '22 at 03:22
  • @user20042973 :) :) I dont answer just to get upvote. I try to help and give them hints, so they can move on. I know how stressful it is – Yilmaz Oct 02 '22 at 03:26