If you’re seeing a SyntaxError: Unexpected token < in JSON at position 0 error in your browser console at angular.js:13920, or Line 13920 or angular.min.js, then it’s likely that you’re working with HTTP API’s, possibly using $resource or $http, and one of the API’s has an error notice or warning in the response body.

For reference, here’s the full error stack I’m talking about:

SyntaxError: Unexpected token < in JSON at position 0
    at JSON.parse (<anonymous>)
    at Q (angular.js:1333)
    at Ot (angular.js:10635)
    at angular.js:10726
    at r (angular.js:321)
    at Nt (angular.js:10725)
    at l (angular.js:11577)
    at a (angular.js:16383)
    at angular.js:16399
    at h.$eval (angular.js:17682)

What it Means

On a general level this error occurs when a JSON object is parsed that has syntax errors in it. Think of something like this, where the message property contains unescaped double quotes.

{
    "success":false,
    "data": [{
        "code": "Oops",
        "message": "This message has "unescaped" quotes."
    }]
}

Most Common Cause

In my experience as a front-end developer the most common cause of this is when an HTTP API is retreived by the browser with a Content-Type:application/json; charset=UTF-8 header set that contains invalid JSON in the response body.

If the server-side throws an error thay breaks a JSON object you’ll see this. A good example of this would be an API response containing a PHP Warning or Notice in the response body when the Content-Type:application/json; charset=UTF-8 header is set.

Here’s an example:

<b>Notice</b>:  Undefined variable: the_post in <b>/path/to/some-api-controller.php</b> on line <b>121</b><br />
{
    "success":false,
    "data": [{
        "code": "SUCCESS",
        "message": "Funky funky API content for you to work with."
    }]
}

In this example (with dummy content) PHP is printing the Notice in my localhost WordPress environment. If you’re seeing this issue in a production environment then you may have a Warning not a Notice.

Other Causes

There are potential solutions available on StackOverflow, but I found that in my case 90% of the time it’s caused by the common scenario described above. If you’re experiencing it and it’s not caused by a broken JSON API response then I’d suggest taking the following steps to track it down:

  1. Find any JSON objects that could be the cause and run them through JSONLint to check for syntax errors

Track Down XHR Errors in Angular

One of the most frustrating aspects of this error is that it can be particularly difficult to find the source of the issue. The stack trace provided by the browser is focused on the JSON.parse() handler within Angular itself, as this is where the XHR response is actually being processed. To get to the bottom of the issue I wrote the following Angular module that will help you find incomplete XHR requests that pass through the $http or $resource services built-in to Angular.

The xhrErrorTracking Module

/**
 * Track Incomplete XHR Requests
 * 
 * Extend httpInterceptor to track XHR completions and keep a queue 
 * of our HTTP requests in order to find if any are incomplete or 
 * never finish, usually this is the source  of the issue if it's 
 * XHR related
 */
angular.module( "xhrErrorTracking", [
        'ng',
        'ngResource'
    ] )
    .factory( 'xhrErrorTracking', [ '$q', function( $q ) {
        var currentResponse = false;

        return {
            response: function( response ) {
                currentResponse = response;
                return response || $q.when( response );
            },
            responseError: function( rejection ) {
                var requestDesc = currentResponse.config.method + ' ' + currentResponse.config.url;
                if ( currentResponse.config.params ) requestDesc += ' ' + JSON.stringify( currentResponse.config.params );

                console.warn( 'JSON Errors Found in XHR Response: ' + requestDesc + '\n' + JSON.stringify( currentResponse.data, null, 3 ) );

                return $q.reject( rejection );
            }
        };
    } ] )
    .config( [ '$httpProvider', function( $httpProvider ) {
        $httpProvider.interceptors.push( 'xhrErrorTracking' );
    } ] );

Once this is installed as a dependency you should see helpful console warn messages appear for any XHR request that is incomplete or doesn’t finish. These are the XHR responses that typically have the in my experience. Hopefully this helps you find and fix the SyntaxError: Unexpected token < in JSON at position 0 error you’re seeing in your browser console.

Track Angular.js $http and $resource JSON errors

If you have any questions, feedback, or suggestions please post comments below.

About the Author

Kevin Leary is a web developer in Boston, MA specializing in enterprise website design and development, online marketing, and conversion optimization.