JSON Parse error: Unrecognized token '<' parse - React Native - javascript

"JSON Parse error: Unrecognized token'<'"
Error is showing while hitting the API. (Response is in the JSON format.) I'm trying to build a login form but I cannot retrieve user data from my database server.
constructor(){
super()
this.state={
email:'',
password:'',
}
}
handleLoginUser(){
fetch('https://"mygoogleclouddatabaseip"/users/login', {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify(this.state)})
.then(response => {
console.log(response);
return response.json();})
.then(responseData => {
console.log(responseData);
let result = JSON.parse(responseData);
return result;})
.then(data => {
if (result.success){
alert("Login successful");
}
else
alert("Unable to Login");
})
}
}

The problem is that your response isn't a valid json and it gives you the error when trying to do response.json().
Please debug it and to handle the case where response isn't a valid json.
Or the other problem can be here
let result = JSON.parse(responseData);
If responseData is already a javascript object, using JSON.parse will give you an error and if response.json() worked, it means that JSON.parse isn't necessary and is giving you the error.
You might ask
Why JSON.parse isn't necessary?
Because response.json() transforms the response to a javascript object and JSON.parse also do that.
The correct way is to use response.json() and not JSON.parse (only if the response is a valid json).

Related

VM101:1 Uncaught (in promise) SyntaxError: Unexpected token < in JSON at position 0

I am using Sandbox for payment testing. Everything works fine till payment and the console throws an error:
Uncaught (in promise) SyntaxError: Unexpected token < in JSON at position 0
The error points to:
fetch(url, {
. I am not sure what's wrong with the Django app. I even have initialized URL at the top:
var url = "{% url 'payments' %}"
onApprove: function(data, actions) {
return actions.order.capture().then(function(details) {
console.log(details);
sendData();
function sendData(){
fetch(url, {
method : "POST",
headers: {
"Content-type": "application/json",
"X-CSRFToken": csrftoken,
},
body: JSON.stringify({
orderID: orderID,
transID: details.id,
payment_method: payment_method,
status: details.status,
}),
})
.then((response) => response.json())
.then((data) => {
window.location.href = redirect_url + '?order_number='+data.order_number+'&payment_id='+data.transID;
})
}
});
}
Either there is an internal server error, or you the server is not sending a Json response. You can check the status by using .then((response)=>console.log(response.status) to check if there is an internal server error, if the console.log shows 500 error code, then it is server error. else the server is not sending proper json response.
You are probably not returning json from the server, try doing res.text() instead of res.json(), and see if that fixes it, if it does, you are not returning proper json from your server.

Why is my JavaScript Fetch not able to get the error object

I have a JavaScript that makes a Fetch post call to the backend of the site. If the post-call goes well, the Fetch is able to handle the response. If something goes wrong in the post-call, the Fetch is not able to handle the error.
This are my codes:
async function startFetch(url, data_post){
return fetch(url, {
method: 'POST', // or 'PUT'
body: JSON.stringify(data_post), // data can be `string` or {object}!
headers:{
'Content-Type': 'application/json'
}
})
.then(response => response.json());
}
async function makeFetch(arrRows){
let url = 'somebackendpost';
for(const item of ArrRows){
let data_post = {};
data.name = item;
await startFetch(url, data_post)
.then(data => {
//when the fetch is okay, this part is executed
console.log(data);
//do other things like output to html
$('#result').append('<p>' + data.result + '</p>');
})
.catch(error ={
//a timeout 504 error occured, but this part seemed not to execute
console.log('error is', error);
//the code below is wrong (but has since been removed then)
//Is this the reason why the catch error part did not work?
//Since the code below has been removed, can I expect the catch error to now work?
$('#result').append('<p>' + data.result + '</p>');
});
}
}
function startProcess(){
//called by button click
let arrRows = ["Row1", "Row2", "Row3"];
makeFetch(arrRows);
}
At the time, the code was executed, there was a server issue. The browser console displayed a Gateway timeout error 504. Here is the console logs:
Fetch failed loading: POST "mysite/somebackendpost"
POST mysite/somebackendpost 504 (GATEWAY TIMEOUT)
error is SyntaxError: Unexpected end of JSON input
at fetch.then.response
Uncaught (in promise) ReferenceError: X is not defined
at startFetch.then.catch.error
Try updating your startFetch method to first check that the fetch response is "ok" before attempting to parse the response as json. This will catch most error scenarios (that are currently going undetected), before you attempt to parse json.
So, an update as follows should allow you to respond to errors correctly:
async function startFetch(url, data_post){
return fetch(url, {
method: 'POST', // or 'PUT'
body: JSON.stringify(data_post), // data can be `string` or {object}!
headers:{
'Content-Type': 'application/json'
}
})
.then(response => {
// Check that the response is valid and reject an error
// response to prevent subsequent attempt to parse json
if(!response.ok) {
return Promise.reject('Response not ok with status ' + response.status);
}
return response;
})
.then(response => response.json());
}
Hope this helps!

Axios POST request fails with error status code 500: Internal Server error

I'm trying to send a POST request locally with a username and password in the body through Axios.
I'm deploying a Flask app on http://127.0.0.1:5000/login, which handles the /login route. The POST request fails with the following error
POST http://127.0.0.1:5000/login 500 (INTERNAL SERVER ERROR)
Error: Request failed with status code 500
at createError (createError.js:16)
at settle (settle.js:18)
at XMLHttpRequest.handleLoad (xhr.js:77)
I researched a bit and thought it might be a problem with CORS, but this doesn't seem to be the case because I tried an Axios GET request and it worked fine (response logged properly). Here's part of my code
axios.get("http://127.0.0.1:5000").then(function(response) {
console.log(response);
}).catch(function(error) {
console.log(error);
})
axios.post("http://127.0.0.1:5000/login", {
username: this.state.username,
password: this.state.password
}).then(function(response) {
console.log(response);
}).catch(function(error) {
console.log(error);
})
Looking at Chrome DevTools, I can see that the POST request payload is properly populated. I then tried printing out the keys server-side in the Flask app using the following code, but I got nothing, empty. (which was expected since the POST request failed)
dict = request.form
for key in dict:
print('form key '+dict[key])
HOWEVER using Postman with the corresponding keys and values works properly and returns a response and prints out the keys (see above). Where is the failure coming from? Why would the POST request fail when a GET seems to work just fine?
Feb 2021. Wasted 2 hours on this. Not much help on this famous library on internet.
Solution:
In the catch block, the error which will always be 500 internal server error
so, use error.response.data instead of error.
Code:
try {
let result = await axios.post( // any call like get
"http://localhost:3001/user", // your URL
{ // data if post, put
some: "data",
}
);
console.log(result.response.data);
} catch (error) {
console.error(error.response.data); // NOTE - use "error.response.data` (not "error")
}
Update:
I ended up writing a common function for handing error:
File: common.app.js
export const errorUtils = {
getError: (error) => {
let e = error;
if (error.response) {
e = error.response.data; // data, status, headers
if (error.response.data && error.response.data.error) {
e = error.response.data.error; // my app specific keys override
}
} else if (error.message) {
e = error.message;
} else {
e = "Unknown error occured";
}
return e;
},
};
More info: https://github.com/axios/axios#handling-errors
So I also got stuck in the same problem and the solution that I found was something like this :
let data = JSON.stringify({
username: this.state.username,
password: password
});
const response = axios.post(url,data,{headers:{"Content-Type" : "application/json"}});
This solution worked for me.
Apparently Axios didn't take kindly to the raw JSON object
{username: this.state.username, password: password}
but passing the data into a FormData object seemed to work just fine!
After working 2 hours, I realized I made a mistake about the body and data. So, in the axios make sure you pass the data like this.
async function loadToken(){
try{
response = await axios({
url: ``,
headers: {
'Authorization': '',
'Content-Type': '',
},
data: '',
method: 'POST'
});
let data = response.data;
return {
tokenInfo:data,
timestamp:new Date().getTime()
}
} catch(err) {
console.log("err->", err.response.data)
return res.status(500).send({ret_code: ReturnCodes.SOMETHING_WENT_WRONG});
}
}
My previous code pass the data like this, which is wrong
async function refreshToken(){
try{
let headers = {
authorization: '',
'Content-Type': ''
}
let url = ``
let body = {
grant_type: '',
refresh_token: global.tokenInfo.refresh_token
}
data = await axios.post(url, body, {headers});
let data = response.data
console.log(data)
return {
tokenInfo:data,
timestamp:new Date().getTime()
}
} catch(err) {
console.log("err->", err.response)
return res.status(500).send({ret_code: ReturnCodes.SOMETHING_WENT_WRONG});
}
}
Simply try my first code, hope that solves your issue.
Most of the time it happens because of using wrong content type header.
Open postman and see "Body" tab. There you can find the content type of your post data. It's also accessible from "Headers" tab. There should be a Content-Type header. The correct format of data you send through a POST request depends on Content-Type header. for example, json content type requires a json (javascript object) data or form-data content type requires a FormData.
To set a header in axios, change the code like this:
axios.post("http://127.0.0.1:5000/login", {
username: this.state.username,
password: this.state.password
}, {
headers: {'Content-Type': 'application/json'}
}).then(function(response) {
console.log(response);
}).catch(function(error) {
console.log(error);
})
I had similar error i had the JSON capital and it should have been lowercase

catching error body using axios post

I am sending a status code 422 from my backend code with response body which contains the description of the error. I am using axios post as below to post a request:
post: function(url, reqBody) {
const request = axios({
baseURL: config.apiUrl,
url: url,
headers: {
'Content-Type': 'application/json',
'Authorization': sessionStorage.getItem('token')
},
method: 'POST',
data: reqBody,
responseType: 'json'
});
return request
.then((res) => {
return res;
})
.catch((error) => {
console.log(error);
return error;
})
}
The problem is when backend is returning error code 422, the error object I am catching has no information about response body. Is there any way I can retrieve the error text?
I had this same issue and the answer (as per Axios >= 0.13) is to specifically check error.response.data:
axios({
...
}).then((response) => {
....
}).catch((error) => {
if( error.response ){
console.log(error.response.data); // => the response payload
}
});
See here for more details.
The "body" of an AXIOS error response depends from the type of response the request had.
If you would like full details about this issue you can see this blogpost: How to catch the body of an error in AXIOS.
In summary AXIOS will return 3 different body depending from the error:
Wrong request, we have actually done something wrong in our request (missing argument, bad format), that is has not actually been sent. When this happen, we can access the information using error.message.
axios.get('wrongSetup')
.then((response) => {})
.catch((error) => {
console.log(error.message);
})
Bad Network request: This happen when the server we are trying to reach does not respond at all. This can either be due to the server being down, or the URL being wrong.
In this case, we can access the information of the request using error.request.
axios.get('network error')
.then((response) => {})
.catch((error) => {
console.log(error.request );
});
Error status: This is the most common of the request. This can happen with any request that returns with a status that is different than 200. It can be unauthorised, not found, internal error and more. When this error happen, we are able to grasp the information of the request by accessing the parameter specified in the snippets below. For the data (as asked above) we need to access the error.response.data.
axios.get('errorStatus')
.then((response) => {})
.catch((error) => {
console.log(error.response.data);
console.log(error.response.status);
console.log(error.response.headers);
})
For those using await/async and Typescript
try {
const response = await axios.post(url, body)
} catch (error) {
console.log(error.response.data);
}
For react native it just worked for me
api.METHOD('endPonit', body)
.then(response => {
//...
})
.catch (error => {
const errorMessage = JSON.parse(error.request.response)
console.log(errorMessage.message)
})
We can check error.response.data as #JoeTidee said. But in cases response payload is blob type? You can get error response body with the below code.
axios({
...
}).then((response) => {
....
}).catch(async (error) => {
const response = error.response
if(typeof response.data.text === function){
console.log(await response.data.text()); // => the response payload
} else {
console.log(response.data)
}
});
I am returning a string from backend but expecting a json as response type. So I need to return an object instead of string for axios to process it properly.
In my case I wanted to retrieve a response 404 error message (body).
I got body with error.response.data but I couldn't display it because the type was ArrayBuffer.
Solution:
axios.get(url, { responseType: 'arraybuffer' }).then(
response => {...},
error => {
const decoder = new TextDecoder()
console.log(decoder.decode(error.response.data))
}
)
Related posts:
Converting between strings and ArrayBuffers

Handling non JSON response with a Body.json() promise

I'm trying to create a scheme to intercept and handle requests from an API middleware, however, for whatever reason I'm unable to properly handle non JSON responses from my API endpoint. The following snippet works just fine for server responses formatted in JSON however say an user has an invalid token, the server returns a simple Unauthorized Access response that I'm unable to handle even though I am supplying an error callback to the json() promise. The Unauthorized Access response message is lost in the following scheme.
const callAPI = () => { fetch('http://127.0.0.1:5000/auth/', {
method: 'GET',
headers: {
'credentials': 'include',
'Accept': 'application/json',
'Content-Type': 'application/json',
'Authorization': 'Basic bXlKaGJHY2lPaUpJVXpJMU5pSXNJbVY0Y0NJNk1UUTVPRE15TVRNeU5pd2lhV0YwSWpveE5EazRNak0wT1RJMmZRLmV5SnBaQ0k2TVgwLllFdWdKNF9YM0NlWlcyR2l0SGtOZGdTNkpsRDhyRE9vZ2lkNGVvaVhiMEU6'
}
});
};
return callAPI().then(res => {
return res.json().then(responseJSON => {
if(responseJSON.status === 200){
return dispatch({
type: type[1],
data: responseJSON,
message: success
});
} else if(responseJSON.status === 401) {
return dispatch({
type: type[2],
message: responseJSON.message
});
}
return Promise.resolve(json);
}, (err) => {
console.log(err.toString(), ' an error occured');
});
}, err => {
console.log('An error occured. Please try again.');
});
Try using text method of Body: res.text().
Try to wrap your response handling code in a try...catch block like this:
return callAPI().then(res => {
try {
return res.json().then(responseJSON => {
[...]
catch(e) {
console.error(e);
}
});
Body.json() throws when the body is actually not JSON. Therefore, you should check if the body contains JSON before you call json() on it. See https://developer.mozilla.org/en-US/docs/Web/API/Response.

Categories