Failure to load https://www.gstatic.com/charts/loader.js

3,560 views
Skip to first unread message

James Handley

unread,
Jul 1, 2019, 6:37:57 AM7/1/19
to Google Visualization API
I have started seeing intermittent problems using Google Visualisation in a customer's Production environment in the last few weeks. I have made no code or infratructure changes.

The system has been stable for 3+ years, and I cannot replicate in a development environment.

The browser being used is Chrome.


When trying to call
google.charts.load('current', { 'packages': ['corechart'] });

I intermittently see:
Uncaught TypeError: Cannot read property 'load' of undefined
    at initialise()

The simplified replication code is:

<html>
<head>
<script type="text/javascript" src="scripts/jquery-3.3.1.min.js"></script>
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
</head>
<body>

<div id="chart">
</div>

function initialise() {
google.charts.load('current', { 'packages': ['corechart'] });
google.charts.setOnLoadCallback(() => {
// .. drawing code
};
}

$(function () {
$('#div').load ('Content/Chart.html', function() { initialise();});
});

</body>
</html>

Unfortunately I do not currently have details of the HTTP response for the request to 'loader.js', but I errors in the Console have not been reported, except the TypeError shown above.


My questions are:
  1. Is there some sort of rate limiting/throttling applied to the 'loader.js' which might be causing this problem - the Production environment has 1,000s of users.
  2. Is it possible the customer's network is slow, meaning the "initialise" code is being called before all the JS has loaded?
    (I thought that using
    $(function () {}); would mean the code wouldn't be called before the entire page had finished loading?)

Daniel LaLiberte

unread,
Jul 1, 2019, 10:46:24 AM7/1/19
to Google Visualization API
The code you copied *could* be OK, but at least part of it is missing (the <script> tag around your code) so I wonder if there might be more going on that might affect when the initialise function is called, or other things that could affect the loader.  Could you point to the actual web page so I can see what else might be involved in the loading process?  

There is no rate limiting or throttling applied to the loader, and the network slowness should not affect the behavior of browsers such that the loader.js code should be loaded and executed before any subsequent scripts are executed.

The loader was changed in the last couple weeks, but I don't believe the changes should affect anything you are seeing, certainly nothing that is timing related.

--
You received this message because you are subscribed to the Google Groups "Google Visualization API" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-visualizati...@googlegroups.com.
To post to this group, send email to google-visua...@googlegroups.com.
Visit this group at https://groups.google.com/group/google-visualization-api.
To view this discussion on the web visit https://groups.google.com/d/msgid/google-visualization-api/46243bf7-52bc-450b-bab7-49ba72f6128c%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


--

James Handley

unread,
Jul 1, 2019, 12:00:12 PM7/1/19
to Google Visualization API
Hi Daniel,

Thank you for getting back to me so quickly - yes, I had forgotten to include the <script> tag in the code I posted above, sorry.

Good to be able to eliminate the throttling, and like you I didn't think the of the javascript would execute until all the scripts were loaded (or failed to load)...
My working theory is that either the 'loader.js' is failing to load at all, or a corrupt version has been cached somewhere - but I want to try and eliminate other possibilities.

The fly in the ointment is that it has been rock solid for the customer for years, and suddenly started having problems since around 17th June, which appear to have been steadily getting worse since then. There has been no code deployment at our end, and we are not aware of any infrastructure changes at the customer's end.

On the other hand, we so far haven't seen it happen from our network.

Getting the client to refresh the page sometimes (but not always) fixes the issue.

It's not going to be so easy to point you at the web-page, as it's a customer specific and commercially sensitive application. Is there anything specific you'd be looking for? It might be possible to spin up a test environment if that will shed any light.

The only two google 'namespaces' the app references are 'google.maps' and 'google.charts'.

The site has been built in TypeScript, and the compiled JS gets bundled by ASP.Net.

The only bits of code which reference google charts/visualization are:

packages.config:
  <package id="google.visualization.TypeScript.DefinitelyTyped" version="0.5.7" targetFramework="net452" />

chart.html:
<div class="chartDiv">
</div>


chart.ts:
namespace XXXX {
    export class Chart  {
        element;

        constructor(ele: JQuery) {
            this.element = ele;
            var me = this;
            this.element.load('Content/Chart.html', () => me.initialise());
        }

        private isChartsLoaded: boolean;

        private chartData: google.visualization.DataTable;
        private classicChart: google.visualization.ColumnChart;
        private chartOptions: google.visualization.ColumnChartOptions;

        private initialise() {
            var me = this;

            me.isChartsLoaded = false;

            // Set a callback to run when the Google Visualization API is loaded.

                         // --- This line sometimes throws the exception ---
            google.charts.load('current', { 'packages': ['corechart'] });

            google.charts.setOnLoadCallback(() => {
                me.isChartsLoaded = true;
                me.drawChart();
                window.addEventListener('resize', function (e) {
                    if (me.classicChart && me.chartData && me.chartOptions)
                        me.classicChart.draw(me.chartData, me.chartOptions);
                });
            });
        }

        private drawChart() {

            // .. removed code checking for data ..

            if (!this.isChartsLoaded || (typeof google === 'undefined') || (typeof google.visualization === 'undefined')) {
                                // --- ... And after that we end up in here whenever drawChart is called. ---
                logger.warn('google.visualization hasn\'t loaded yet...');
                return;
            }

            // .. removed code as it is never reached ..
        }
   }
}

MainPage.html:
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>XXXXX</title>
    <META HTTP-EQUIV="Pragma" CONTENT="no-cache">
    <META HTTP-EQUIV="Expires" CONTENT="-1">

    <!-- style sheets loaded here -->

    <script src="bundles/jquery"></script>
    <script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
    <script src="bundles/app-javascript"></script>
</head>
<body>
   <!-- Various other widgets been removed for clarity, but none of them use google charts -->

   <div id="chart" class="container">
     <div class="initialising">Please Wait</div>
   </div>
</div>

<script type="text/javascript">
    // -- other widgets removed
    var chart;

   $(function () {
       // -- other widgets removed
       chart = new XXXX.Chart($('#chart'));
    });
</script>
</body>
</html>

In the Chrome console, the only error reported is the TypeError, and I get the same behaviour if I manually break the script reference(e.g. change it to 'loader-broken.js')

With thanks,
James

Daniel LaLiberte

unread,
Jul 1, 2019, 1:08:05 PM7/1/19
to Google Visualization API
Hi James,

The change to the loader was made on June 13, so it is plausible your clients didn't notice the problem until the 17th.    The changes involved adding support to handle redirects from the old jsapi loader, which may die at any moment before we have time to handle the redirects more gracefully.   So the new loader now exports 'google.load' if it is not already defined, and handles calls of google.load() and google.setOnLoadCallback().  If the jsapi loader is being used along with the new loader, that might cause some confusion, but I believe it would only be a problem if you are calling google.load().    

It appears that you are loading the 'maps' api directly, and not via the old jsapi loader, which is good.  Hmm, that makes me wonder if we might still have a problem once we are redirecting jsapi, in the situation that you load both jsapi and the new loader.   Users of some of the older versions of the map-related charts were forced to load jsapi (to also load 'maps', so we could use its geocoding service) and the new loader.   Anyway, this is something to check on, but probably not relevant for you.

If you have never seen the problem occur from your network, I would be inclined to guess this is related to the local configuration of the network or possibly caching servers, though I can't think why it would be a problem.  The loader is a single file that then loads a version-specific loader, which then loads the necessary modules of the specific version.  But all that is irrelevant if google.charts.load is not defined in the first place because google.charts is not defined.  Did the loader.js load, but fail to execute?  Or is the loading still pending?  It would be good to check the debugger 'network' tab to see what happened to the loading of loader.js.

If I were in your situation, I would just try to work around the problem, maybe by checking whether google.charts is defined before calling google.charts.load.    If it is not defined, call it again in a timeout.   If it fails after a few such timeouts, there is probably something more serious going on, such as a failure during execution of the loader.

Hope that helps.



--
You received this message because you are subscribed to the Google Groups "Google Visualization API" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-visualizati...@googlegroups.com.
To post to this group, send email to google-visua...@googlegroups.com.
Visit this group at https://groups.google.com/group/google-visualization-api.

For more options, visit https://groups.google.com/d/optout.

James Handley

unread,
Jul 2, 2019, 4:20:08 AM7/2/19
to Google Visualization API
Hi Daniel,

That's really helpful - thank you. Our next release does have the check and timeout you suggest, so if we're really luckt that will sort it out.

In terms of how we're using maps. aside from the JS API load (which I showed above), I just construct the maps object in the widget initialise method like the charts above.

            this.googlemap = new google.maps.Map(this.element.children("div")[0], options);

Interestingly, we are not getting any reports of the maps not working properly; but then we do have a Premium Plan for the Maps APIs, hence my original question over whether the charts were being throttled at your end...

The only thought I;ve and is whether there is any chance the TypeScript packages might be interfering?

google.visualization.d.ts:
// Type definitions for Google Visualisation Apis
// Project: https://developers.google.com/chart/
// Definitions by: Dan Ludwig <https://github.com/danludwig>, Gregory Moore <https://github.com/gmoore-sjcorg>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped

declare namespace google {
    function load(visualization: string, version: string, packages: any): void;
    function setOnLoadCallback(handler: Function): void;
    function setOnLoadCallback(handler: () => void): void;

    // https://developers.google.com/chart/interactive/docs/basic_load_libs
    namespace charts {
        function load(version: string, packages: Object): void;
       // ...etc
    }

    //https://developers.google.com/chart/interactive/docs/reference
    namespace visualization {
    }

   // .. etc
}


google.maps.d.ts:
// Type definitions for Google Maps JavaScript API 3.25
// Project: https://developers.google.com/maps/
// Definitions by: Folia A/S <http://www.folia.dk>, Chris Wrench <https://github.com/cgwrench>, Kiarash Ghiaseddin <https://github.com/Silver-Connection/DefinitelyTyped>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped

declare namespace google.maps {
  export class Map extends MVCObject {
     constructor(mapDiv: Element, opts?: MapOptions);
     fitBounds(bounds: LatLngBounds): void;
     // ... etc
  }
}

I'm not sure if these files get baked into the app - I had thought that they were just compile time support files?

I'm hoping to get access to the debugger network tab of a cusomter experincing the problem today, and if I do then I'll post the results.

Many thanks again for all your help.

James

James Handley

unread,
Jul 2, 2019, 9:37:01 AM7/2/19
to Google Visualization API
Dear Daniel,

I've managed to get hold of a screenshot of network debug from the customer machine, and while on this occasion it did manage to load the charts, the network traffic looked very different from what I see when I access the app.

When I load it I get:
The client however shows:
I'm sorry I don't have the full details of the URLs - I only have a screenshot.

I'm not sure what exacly is going on with the 307 responses, or the auD, but it could explain why the google.charts.load call is happening before the final 'loader.js' call is complete, in which case the test/timeout loop should resolve it?

Daniel LaLiberte

unread,
Jul 2, 2019, 10:43:43 AM7/2/19
to Google Visualization API
Curious, but confusing.  

The temporary redirects (307) are surprising because we don't use them now, though we did use them a couple years ago to redirect requests to the 'current' version.  Because of caching, different people were getting different incompatible modules from different versions.  Instead, now we effectively do the redirect via the browser by explicitly loading the right files.  No http redirects are involved.  So where are they coming from?

For each page, there should only be one load of the top-level charts/loader.js, and one version-specific loader.  If there is more than one load of the loader, with inconsistent loading patterns, that could explain occasional failures.

--
You received this message because you are subscribed to the Google Groups "Google Visualization API" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-visualizati...@googlegroups.com.
To post to this group, send email to google-visua...@googlegroups.com.
Visit this group at https://groups.google.com/group/google-visualization-api.

For more options, visit https://groups.google.com/d/optout.

James Handley

unread,
Jul 2, 2019, 11:32:15 AM7/2/19
to Google Visualization API
It is the same code in both places, and I am definitely only loading loader.js once in my code, which is the static HTML reference (you can see from the network debug that all the subsequent loads are being added dynamically from downloaded javascript).

So are you saying I can rule out the 307s being generated by Google's servers? In which case, surely the only other option is an HTTP proxy/gateway? This particular customer runs a closed and quite restricted network, and I believe all Internet traffic is routed through proxies.

With thanks,
James

Daniel LaLiberte

unread,
Jul 2, 2019, 11:57:31 AM7/2/19
to Google Visualization API
I am not completely sure that the gstatic server might not do some redirecting to balance load around the world, but I would expect a redirect to go to a different URL in that case.  However, the two requests with funky labels are more suspicious.  
    • auD?origurl=http...       307  557 bytes [loader.js] (don't know url, except it contains 'gstatic')
    • loader.js?_sm_au_=..  307 349 bytes [auD] (don't know url, except it contains 'gstatic')
    Some kind of proxy/gateway might explain it, so it would be interesting to see the http headers at least.


    --
    You received this message because you are subscribed to the Google Groups "Google Visualization API" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to google-visualizati...@googlegroups.com.
    To post to this group, send email to google-visua...@googlegroups.com.
    Visit this group at https://groups.google.com/group/google-visualization-api.

    For more options, visit https://groups.google.com/d/optout.

    James Handley

    unread,
    Jul 8, 2019, 4:24:12 AM7/8/19
    to Google Visualization API
    Hi Daniel,

    Thank you for all your help on this - I managed to get access to the request logs as you suggested, and it turns out there is a corporate firewall/proxy messing things up.

    Basically the request for "loader.js" is being intercepted and redirected to a network security holding message, which sometimes redirects to a network security login page. Unsurprisingly this causes some problems for the Google charts on the app.

    I suppose it's possible that this is related to the loader change, if something which was introduced at your end which the corporate firewall doesn't like - but in any case it doesn't appear to be eitehr my code or the google loader which is the root cause!

    Many thanks again,
    James

    Daniel LaLiberte

    unread,
    Jul 8, 2019, 9:30:46 AM7/8/19
    to Google Visualization API
    Good to hear that the loader is not the cause of problems, but it is still a mystery exactly what is happening, and how the update of the loader might have exposed problems.    Maybe there is just some additional asynchrony involved in loading through the firewall/proxy, and if so, just waiting long enough for the loader to finish loading will be a sufficient work around.

    --
    You received this message because you are subscribed to the Google Groups "Google Visualization API" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to google-visualizati...@googlegroups.com.
    To post to this group, send email to google-visua...@googlegroups.com.
    Visit this group at https://groups.google.com/group/google-visualization-api.

    For more options, visit https://groups.google.com/d/optout.
    Reply all
    Reply to author
    Forward
    0 new messages