_proto._scriptMethod: RayGun not reporting errors in initialize/update functions

Good afternoon all,

I am implementing RayGun, an error-tracking service; it is working in all places, EXCEPT in the initialize/update functions (and I assume in all other “script methods”).

When I pause the code with a debugger, I get the following behavior:

  • In normal functions, the thread ends at the error, and RayGun somehow finds and reports it.
  • However, in initialize/update functions, when an error gets thrown, the thread does not end, but rather enters the catch block of a function called _scriptMethod(script, method, arg), and the error doesn’t get reported to RayGun.

I assume that this function is invoked on all “script methods”, and it is somehow preventing RayGun from finding the error.

This is what that function looks like:

_proto._scriptMethod = function _scriptMethod(script, method, arg) {
			try {
				script[method](arg);
			} catch (ex) {
				script.enabled = false;

				if (!script._callbacks || !script._callbacks.error) {
					console.warn("unhandled exception while calling \"" + method + "\" for \"" + script.__scriptType.__name + "\" script: ", ex);
					console.error(ex);
				}

				script.fire('error', ex, method);
				this.fire('error', script, ex, method);
			}
		};

Does anyone know what I can do to solve this? (by “solve” I mean, get RayGun to report errors inside of script methods).

One solution is to wrap every script method in a try/catch block, and send the error manually to RayGun in the catch block. However, if there is a way to avoid this, that would be incredible, because the automatic reporting is much cooler and more maintainable.

Thank you very much for any help anyone might be able to provide :slight_smile:

Best,
Michael King.

(P.S. The way I have implemented RayGun is by storing the RayGun scripts in an S3 bucket, and then adding links to those 2 scripts in the “external scripts” section of the Editor settings. From there, it is magically working, except in the script methods).

Update: along the lines of this StackOverflow post, I’m hoping that I could somehow override this method, send the error manually to RayGun, and then call the original method.

This would not be the exact syntax (if someone could provide a way to actually do this correctly, I’d be forever grateful, I haven’t been able to figure it out), but the idea would be something like this:

pc.Entity.prototype.scriptMethodOriginal = pc.Entity.prototype.scriptMethod;

pc.Entity.prototype.scriptMethod = function() {
    var c = this.scriptMethodOriginal();
    // do my stuff, i.e. send error to raygun
    return c;
}

Best,
Michael

I’ve had a look at the engine code here: https://github.com/playcanvas/engine/blob/bdb32106ae7cd4e184b997d603d6b0d2f128d4b8/src/framework/components/script/component.js#L380

The try/catch code is only here for debug builds of the engine. If you want to try the RayGun integration in the launch tab, untick debug in the launch tab options:

Interesting. Ok, so I just tried this – what happens now is that when the code hits the error (tried it in the initialize method of one of our controllers), the code enters the following code, which starts* like this (but it is super long so I am only pasting part of it :slight_smile: ), and does not get reported to raygun:

/**
 * @license
 * PlayCanvas Engine v1.52.3 revision 876c42483
 * Copyright 2011-2022 PlayCanvas Ltd. All rights reserved.
 */
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t="undefined"!=typeof global

I also tried creating a method outside of initialize that I call from within initialize (to throw the error), but the same functionality occurs.
Any ideas? :open_mouth:

Can you put together a public project to reproduce the issue please? I’m having a bit of a hard time visualising this as I can’t see why it wouldn’t work outside of a debug build of the engine

Hi yaustar, we eventually solved that specific error by overriding console.error as follows:

 var originalErrorLog = console.error;
        console.error = function(err) {
            Tools.prototype.sendCustomErrorToRaygun(err);
            originalErrorLog.apply(console, arguments);
        };

However, we are now facing a different “more serious” problem – everything works fine in development, but when we publish a build, all errors are reported to RayGun with no stacktrace and with the title “script error”.

From reading on RayGun about this, it seems that it might have to do with cross-browser restrictions, but I am not well-versed on this matter and am a bit confused about how to proceed.

This guide and this blog post explain in detail, but what seems relevant is the following snippet:

“Script errors are mostly likely to be caused by an error within a script that’s hosted on a different domain (for example, CDN scripts). As a result, the user’s browser stops the script from executing in order to prevent an attack called cross-site request forgery. However, it may also be a problem if the script is stored on the same domain but uses a different port, protocol (for example http:// instead of https://), or subdomain.”

The guide gives a few possible solutions, but I am completely confused as to where to begin my attempts.

Could you provide me any guidance? :pray:

Best,
Michael

On playcanv.as hosted builds, the scripts and assets are actually hosted on a S3 bucket on Amazon and therefore on a different domain.

When you self host, you shouldn’t have this problem