Uncaught (in promise) SyntaxError: Unexpected end of JSON input
Asked Answered
S

6

22

I am trying to send a new push subscription to my server but am encountering an error "Uncaught (in promise) SyntaxError: Unexpected end of JSON input" and the console says it's in my index page at line 1, which obviously is not the case.

The function where I suspect the problem occurring (because error is not thrown when I comment it out) is sendSubscriptionToBackEnd(subscription) which is called in the following:

function updateSubscriptionOnServer(subscription) {
  const subscriptionJson = document.querySelector('.js-subscription-json');
  const subscriptionDetails = document.querySelector('.js-subscription-details');

  if (subscription) {
    subscriptionJson.textContent = JSON.stringify(subscription);
    sendSubscriptionToBackEnd(subscription);
    subscriptionDetails.classList.remove('is-invisible');
  } else {
    subscriptionDetails.classList.add('is-invisible');
  }
}

The function itself (which precedes the above function):

 function sendSubscriptionToBackEnd(subscription) {
  return fetch('/path/to/app/savesub.php', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json'
    },
    body: JSON.stringify(subscription)
  })
  .then(function(response) {
    if (!response.ok) {
      throw new Error('Bad status code from server.');
    }

    return response.json();
  })
  .then(function(responseData) {
    if (!(responseData.data && responseData.data.success)) {
      throw new Error('Bad response from server.');
    }
  });
}

I have tried replacing single quotes with double quotes in the fetch call but that yields the same results.

I know that the JSON should be populated because it prints to the screen in the updateSubscriptionOnServer() function with subscriptionJson.textContent = JSON.stringify(subscription);, and I used that output in the google codelab's example server to receive a push successfully.

EDIT: Here is the JSON as a string, but I don't see a mistake in syntax:

{"endpoint":"https://fcm.googleapis.com/fcm/send/dLmthm1wZuc:APA91bGULRezL7SzZKywF2wiS50hXNaLqjJxJ869y8wiWLA3Y_1pHqTI458VIhJZkyOsRMO2xBS77erpmKUp-Tg0sMkYHkuUJCI8wEid1jMESeO2ExjNhNC9OS1DQT2j05BaRgckFbCN","keys":{"p256dh":"BBz2c7S5uiKR-SE2fYJrjPaxuAiFiLogxsJbl8S1A_fQrOEH4_LQjp8qocIxOFEicpcf4PHZksAtA8zKJG9pMzs=","auth":"VOHh5P-1ZTupRXTMs4VhlQ=="}}

Any ideas??

Saleable answered 12/4, 2017 at 6:56 Comment(11)
Can you supply us with the response from the server?Neidaneidhardt
Maybe the problem is, that you use JSON.stringify() instead of JSON.parse()?Shrieval
What's your JSON look like, seems like a syntax errorCapel
I agree with alex. Forgot you used POST.Capel
@alexkucksdorf, wouldn't JSON.parse() be used on the server side when I receive it? I'm trying to send the data in the code here.Saleable
You are telling the server by using the Content-Type you will send it JSON, but actually you are sending a string if you use JSON.stringify(). The server can handle pure JSON.Shrieval
I removed JSON.stringify() and received the same error. I tried JSON.parse() and received the same errorSaleable
Did you remove both occurrences of JSON.stringify()?Shrieval
the first occurrence of JSON.stringify() inside updateSubscriptionOnServer() is necessary to print the JSON to the screen. Alas, even if I remove it I still have the same error.Saleable
I don't know in which format your JSON comes, but maybe it is sufficient to just use your subscription as body for your POST.Shrieval
Let us continue this discussion in chat.Saleable
G
20

This might be a problem with the endpoint not passing the appropriate parameters in the response's header.

In Chrome's console, inside the Network tab, check the headers sent by the endpoint and it should contain this: Example of proper response to allow requests from localhost and cross domains requests

Ask the API developer to include this in the headers:

"Access-Control-Allow-Origin" : "*", 
"Access-Control-Allow-Credentials" : true 
Graybeard answered 21/4, 2017 at 15:54 Comment(1)
I changed my server endpoint returning http 200 instead of http 2004 status code and resolved it this way.Eurasian
V
8

This happened to me also when I was running a server with Express.js and using Brave browser. In my case it was the CORs problem. I did the following and it solved the problem in my case: (since this is an Express framework, I am using app.get)

-on the server side:

 res.set({
        "Content-Type": "application/json",
        "Access-Control-Allow-Origin": "*",
    });

-on client side I used Fetch to get data but disabled the CORS option

// mode: "no-cors" //disabled this in Fetch

That took care of my issues with fetching data with Express

Valetudinarian answered 2/2, 2021 at 3:13 Comment(0)
E
4

This can be because you're not sending any JSON from the server OR This can be because you're sending invalid JSON.

Your code might look like res.end();

Endo answered 11/10, 2020 at 5:20 Comment(0)
B
2

One of the pitfalls is that returned data that is not a JSON but just a plain text payload regardless of headers set. I.e. sending out in Express via something like

res.send({a: "b"});

rather than

res.json({a: "b"});

would return this confusing error. Not easy to detect in network activity as it looks quite legit.

Beccafico answered 5/6, 2020 at 4:29 Comment(0)
M
1

For someone looking here later. I received this error not because of my headers but because I was not recursively appending the response body to a string to JSON.parse later.

As per the MDN example (I've taken out some parts of their example not immediately relevant):

reader.read().then(function processText({ done, value }) {
    if (done) {
      console.log("Stream complete");
      return;
    }
    result += chunk;
    return reader.read().then(processText);
  });

For my issue I had to

  1. Use a named function (not an anonymous ()=>{}) inside the .then
  2. Append the result together recursively.
  3. Once done is true execute something else on the total appended result

Just in case this is helpful for you in the future and your issue is not header related, but related to the done value not being true with the initial JSON stream response.

Macey answered 29/11, 2019 at 14:29 Comment(0)
T
0

I know this question has already been answered but just thought I add my thoughts.

This will happen when your response body is empty and response.json() is expecting a JSON string. Make sure that your API is returning a response body in JSON format if must be.

Teledu answered 1/4, 2022 at 10:5 Comment(1)
Not sure why you got a downvote, this was a valid answer.Gunas

© 2022 - 2024 — McMap. All rights reserved.