Search code examples
javascriptreactjsreact-nativefetch-api

fetch returns SyntaxError: Unexpected token T in JSON at position 0


I'm trying to use the Javascript fetch method, however, it does not seem to work asynchronously.

Here's my code:

fetch(`${global.URL}${url}`, requestConfig)
  .then(res => res.json())
  .then(res => {
    console.log('response', res);
    return res;
  })
  .catch(error => {
    console.log('error: ', error)
  })

I get the following error 70% of the time, then the other 30%, a valid response is received, when I save the file and it re-renders, it sometimes works.

error:  SyntaxError: Unexpected token T in JSON at position 0
    at parse (<anonymous>)
    at tryCallOne (core.js:37)
    at core.js:123
    at JSTimers.js:277
    at _callTimer (JSTimers.js:135)
    at _callImmediatesPass (JSTimers.js:183)
    at Object.callImmediates (JSTimers.js:446)
    at MessageQueue.__callImmediates (MessageQueue.js:396)
    at MessageQueue.js:144
    at MessageQueue.__guard (MessageQueue.js:373)

I've tried calling it inside and async/await function but it does not help.

EDIT 1:

this is how I make my requests

const authenticityToken = global.TOKEN

const query = (url, config) => {
  const requestConfig = {
    credentials: 'same-origin',
    ...config,
    headers: {
      'X-Requested-With': 'XMLHttpRequest',
      'Content-Type': 'application/json',
      Accept: 'application/json',
      Authorization: authenticityToken,
    },
  }

  return fetch(`${global.URL}${url}`, requestConfig)
  .then(res => res.json())
  .then(res => {
    console.log('response', res);
    return res;
  })
  .catch(error => {
    console.log('error: ', error)
  })
  // .then(handleResponseError)
}

export const get = (url, data) =>
  query(data ? `${url}?${stringify(data)}` : url)

export function fetchUser() {
  return (
    get('/api/v3/me/')
  )
}

Then I call the function inside my component like so:

  const fetchUserAction = () => {
    fetchUser()
    .then((response) => {
      if(response) setUser(response.data)
    })
  }

  useEffect(() => {
    fetchUserAction()
  }, [])

Solution

  • This type of error usually happens when your server returns something which is not JSON. In my experience, 99% of the time the server is returning a generic error message. Often times servers will have a generic "catch all" error handler which returns something like:

    There was an error processing your request.
    

    In this case, if you tried to use JSON.parse (or res.json() in your case), you would get the error you are experiencing. To see this, paste this into your console:

    JSON.parse("There was an error processing your request.")
    //-> Uncaught SyntaxError: Unexpected token T in JSON at position 0
    

    Solution 1: Usually the server will set a proper status code whenever there is an error. Check to make sure the response status is 200 before parsing:

    fetch('...').then(res => {
      if (res.status !== 200) {
        throw new Error(`There was an error with status code ${res.status}`)
      }
      return res.json()
    )
    

    Solution 2: Update your server code to return an error message in JSON format. If you're using node and express, this would look something like this:

    function errorHandler (err, req, res, next) {
      if (res.headersSent) return next(err)
    
      const message = 'There was an error processing your request.'
      res.status(500)
      if (req.accepts('json')) {
        // The request contains the "Accept" header with the value "application/json"
        res.send({ error: message });
        return;
      }
      res.send(message);
    }
    

    Then, you would update your frontend code accordingly:

    fetch('...')
    .then(res => res.json())
    .then(res => {
      if (res.error) {
        throw new Error(res.error)
      }
      return res
    )