I'm working on some flash app. Now, to test customer side of it I can use Flash Player debugger version that will save logs and show error messages. When it's deployed on the customer side - they will have a regular Flash Player version which means I will have no access to error messages if errors will happen. So I would like to equip it with some tool that would capture all of my trace messages in code and errors text. As for trace messages that's fairly simple, I just override the function in my code so it sends a POST request with trace message to a logger server, but how can I get a hold of the error message? Is there a known approach to this or some trick that somebody can suggest?
You can install the debug version of flash as your browser's default (in Chrome, you must disable the built-in player), so if you wanted to test user experience and debug, this would be the ideal solution.
However, to answer your question: there's no method for universally catching all errors, and redirecting them (that I know of). You'd have to encapsulate problem code ahead of time with try...catch statements, and send the property back on catch. For example:
try {
this["foo"]();
} catch (e:Error) {
trace(e);
}
In the debug version, the traced value would be TypeError: Error #1006: value is not a function. And while the standard version will only output TypeError: Error #1006, (a notably less descriptive error), what we're missing is any reference to where the error occured. To get this, we need to use Error.getStackTrace() to see the call stack and the line where the error occurred. In debug, this outputs the following:
TypeError: Error #1006: value is not a function.
at Shell_fla::MainTimeline/init()[C:\Projects\shell.as:91
In the standard client, we get a dissapointing null. In short, you cannot get any valuable info from the client versions.
The best advice I can give is to write around your problem code with your own custom error reports. For example, catch IO errors and trace the file it failed to load, or if you're expecting an object.foo, first try if (object.hasOwnProperty("foo")) { // do something } else { trace("foo not found in " + object.name) }. Code defensively.
Cheers,
I've discovered this post on StackOverflow:
How to catch all exceptions in Flex?
It answers my question, strange that I haven't ran into it while I was googling prior to asking.
Related
I'm having trouble with my Deno program. I'm getting messages like this:
error: Uncaught (in promise) Error: No such host is known. (os error 11001)
at deno:core/01_core.js:106:46
at unwrapOpResult (deno:core/01_core.js:126:13)
at async Object.connect (deno:extensions/net/01_net.js:219:13)
Then deno exits.
I don't know how to debug this. This stack trace only points to code that comes with Deno, not to my code.
I've searched my code and I've put a .catch() or a try/catch everywhere I can think of, but that did not help.
Is there anything I can do to help me find the problem? I'd love it if I could get a complete stack dump. Or if I could have the debugger pause at the problem. Or if you have any other suggestions.
Thanks!
Edit 8/29/2021
I found two bugs in my code. Here are the actual bugs. It was a serious pain to track these down. I'm still looking for a tool or process to help the next time I make a silly mistake like this.
Bug #1:
I was using try/catch (shown in red) when I should have been using .catch() (shown in green). My try/catch did nothing. If there was an error sending the data, that would cause my program to crash.
Bug #2:
const promise = Deno.connect(options);
promise.catch(reportError);
promise.then(longRunningTask);
await someOtherPromise;
promise.then(connection => {
// We never get to here.
try {
connection.close();
} catch {
console.log("🙁");
}
});
// And we never get to here.
The code I've shown here was spread throughout a much longer program. I did not understand the rules regarding promises. The second .then() requires a second .catch().
Here was one of my attempts to solve this problem. I told VS code to break on all exceptions. It seems to ignore my request. I never got to a breakpoint, but the debug console shows that the program crashed because of an exception.
I would like to have many devices testing a game, and I find the best way to debug a game and solve specific code problems is to have the device connected and in debug mode in Adobe ANIMATE, that way I can catch any Errors in the Output window.
For Example, if I am debugging and connected to Animate, the output window will throw errors like :
ReferenceError: Error #1065: Variable bg_storage is not defined.
at global/flash.utils::getDefinitionByName()
at Game/stageAdd()[/Users/**/Game.as:360]
Now I know exactly what the problem is and where to find it. I love errors like this.
My question :
If I didn't have a device connected to Animate in Debugging mode, is there a way to make the game detect any errors thrown and store them as a String, that way I can put up a big text block on the game of the error string and keep track.
or at least a way to log them some how?
Ex :
If an error is thrown, have that error text set as a String variable, then have a text box write out that String variable.
I hope that isn't too confusing. If I am going about debugging in a poor way, I would love to know what you guys do to keep track of errors without being connected to debug mode.
EDIT
I can see an approach is you to add an uncaughtErrorEvent event to each function to be able to catch these errors...
loadbar.uncaughtErrorEvents.addEventListener(UncaughtErrorEvent.UNCAUGHT_ERROR ... )
I am trying to make it so any error thrown in any part of the game will trace that error somewhere to a String value that I can call, so that I can see any error thrown during a play test session without being connected to debug mode.
Thanks!
Sure. There's a class intended exactly for that: https://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/events/UncaughtErrorEvent.html See examples at the bottom of the page to listen to the right instances for that event.
You are also free go grab my own class that does the thing you want: https://bitbucket.org/thydmitry/ru.delimiter/src/2756fadd741a6d44276fde1701470daf24cebfa8/classes/ru/delimiter/utils/Log.as?at=default&fileviewer=file-view-default
You will need to add it to your project and then call in the main document class (in constructor, preferably):
Log.create(this);
Log.handleExceptions(this, true);
I am using an imported class for a vimeo player in AS3, it is the official vimeo player api (vimeo.com). I want to handle any Security Errors that an instance of the class throws (they get thrown when the obect fails to load an external URL for a video). This is what I have got:
var clipPlayer = new VimeoPlayer("5d22d3942a54d7c75b931bab4a911857", videoID[clickedClip], fullVideoWidth, fullVideoHeight, "10", 2);
clipPlayer.addEventListener(SecurityErrorEvent.SECURITY_ERROR , vimeoError);
Later in the code ofcourse, I've got the function that handles the event:
function vimeoError (e : SecurityErrorEvent) : void {
trace("vimeo player failed to load");
}
This all seems straight forward, but yet the Error Handler is not firing. I must be missing something here... Maybe you can't register this kind of event listener on a VimeoPlayer object. However, I am pretty certain it is the VimeoPlayer object throwing them. Here is an example of what I am getting:
Error opening URL
'http://api.vimeo.com/moogaloop_api.swf?oauth_key=5d22d3942a54d7c75b931bab4a911857&clip_id=21185860&width=500&height=281&fullscreen=0&fp_version=10&api=1&cache_buster=565.7249609939754'
SecurityError: Error #2000: No active security context.
Dispatched error events are separate from thrown Errors. In many cases both kinds can occur, and then you need to listen for the former and catch the latter with a try statement around the code that may throw. The error you quote seems to be of the thrown variety (as events typically stringize to something involving square brackets).
I'm really struggling to resolve a stack underflow that I'm getting. The traceback I get at runtime is:
VerifyError: Error #1024: Stack underflow occurred.
at flash.events::EventDispatcher/dispatchEventFunction()
at flash.events::EventDispatcher/dispatchEvent()
at flash.net::URLLoader/onComplete()
This is particularly difficult to debug because when I run in debug mode it does not happen at all. It only happens when compiled as a release.
Does anyone have any tips on how to debug a Stack Underflow? Are have a clean explanation of what that means for Flash?
In case it helps, this error is occurring when I click a button whose handler makes an RPC call, which uses a URLLoader, an AsyncToken, and then invokes the set of AsyncResponder instances associated with the AsyncToken. With some server-side logging as well as some logging hacked into the swf, I know that the UrlLoader is successfully doing and GET'ing a crossdomain.xml file, is correctly processing it (ie: if I wreck it, I get a security error), and is also successfully completing the "load" request (the server sends the data). The underflow seems to be happening in the Event.COMPLETE listening/handling process (as is, of course, implied by the traceback as well).
mxmlc used = from flex_sdk_4.5.0.20967
Example player (I've tried a few) = 10.2.153.1
UPDATE: My specific problem is solved... but I'm leaving the question as-is since I would like to know how to generally debug such a problem, rather than just getting my specific solution.
In my code I had the following Application definition:
<s:Application height="100%" width="100%"
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
initialize="InitData();">
Note that the code is/was attached to the initialize event.
InitData() and relevant defintions are/were:
import classes.RpcServerProxy;
public var SP:RpcServerProxy;
public function InitData():void {
SP = new RpcServerProxy("http://192.168.1.102:1234");
}
When I switched the InitData() call to be on the onCompletion event instead of initialize (thanks J_A_X!), the problem goes away entirely. What seems to have been happening was that the Event.COMPLETE event handler (onComplete in the stack trace) was using the global SP object. Something about the release (vs debug) compilation must have been affecting the startup timing of the SP variable initialization. Moving the handler later to the onCompletion event resolved all issues.
As said above, I would still like to know what tricks/tools are available for debugging initialization issues like this.
UPDATE 2:
applicationComplete seems to be an even better event than creationComplete to put application initialization code. See this blog entry for some explanation, and and this video (around 4:25) by an Adobe Tech Evangelist for an example of simple "start of application" data initialization.
I got rid of this error by adding compiler argument:
-omit-trace-statements=false
Stack underflow basically means the compiler messed up.
You can use SWFWire Inspector to look at the bytecode of the event handler, if you want to know exactly how it messed up. You can also use SWFWire Debugger to see which methods were called, but in this case, you already knew where it was happening.
If you post the broken swf, I can give you more info.
Sean is right that to debug it you can look at the byte code, but that didn't sound appealing to me.
Based on my experience and research, it is often due to the presence of a trace statement that incorrectly gets compiled out in release mode, and generates invalid byte code. So, I would say to "debug" it, "Look for places where you are using trace. Try commenting them all out in the offending function and see if the issue goes away."
In my case, it was a trace statement as the first line of a catch block:
catch (e:TypeError) {
trace(e.getStackTrace()); //This line is the problem
throw new Error("Unexpected type encountered");
}
I found someone else with this exact issue here.
This code also leads to stack underflow only in release mode (flag -debug=false):
true && trace('123');
mxlmc flex sdk version 4.5.0.20967, flashplayer version 10.3.181.14 (linux).
Check your code for similar expressions.
This code caused me issues when I compiled a release candidate from flash builder 4.5
public function set configVO( value:PopupConfigVO ):void
{trace("CHANGING")
Resolved by inserting a space between the the trace and curly brace
public function set configVO( value:PopupConfigVO ):void
{ trace("CHANGING")
Hope this helps.
For people looking for the same problem, I just got this caused by a trace statement in the 'default' case of a switch statement. Commented out the trace, stack underflow resolved.
Interesting... I was getting this error with a SWF that I'd pulled off the web, an Away3D based graphics demo. At the time I was running this on the Tamarin VM rather than the actual Flash/AIR runtimes, so could stick a breakpoint on the "verifyFailed(kStackUnderflowError)" line and see what was happening.
The -Dverbose flag also helped find the culprit:
typecheck MethodInfo-1480()
outer-scope = [global]
[Object~ Object] {} ()
0:pop
VERIFY FAILED: Error #1024: Stack underflow occurred.
And looking at the ABC using SWFInvestigator, I found this:
var function(Object):void /* disp_id=0 method_id=1480 nameIndex = 0 */
{
// local_count=2 max_scope=0 max_stack=0 code_len=2
// method position=52968 code position=155063
0 pop
1 returnvoid
}
So there is an obvious issue where the 'trace' has been removed but the compiler has put a 'pop' in there: I wouldn't have thought this was needed as a trace call should presumably have been made via 'callpropvoid'?
Quite why this doesn't fail on AIR/Flash I don't know..
Anyway: looks to me like an ASC compiler problem i.e perhaps one of the ActionScript3 compilers had a fault with this - hence the workarounds that have been mentioned so far.
It's quite simple, and it doesn't have anything to do with spaces before or after brackets, trace commands or whatever else: it's just 1 really simple thingy:
DO NOT LOOP EMPTY!
Meaning, while developing, we all //comment some lines sometimes, and when that results in
for (...) {
// skip for now
}
the compiler gets :
for(...){}
and that my good friends, is something the compiler doesn't like!
so, NO empty loops, and you're on your way again...
Happy hunting,
P.
I had the exact same problem, but in my case the cause of the problem was a trace statement in a place where the compiler didn't expect it to find it, right after a package declaration at the beginning of the class:
package utils
{
trace ("trace something here");
And that's why compiling in debug mode removed the problem.
I have a DLL with some COM objects. Sometimes, this objects crashes and register an error event in the Windows Event Log with lots of hexadecimal informations. I have no clue why this crashes happens.
So, How can I trace those COM objects exceptions?
The first step is to lookup the Fail code's hex value (E.G. E_FAIL 0x80004005). I've had really good luck with posting that value in Google to get a sense of what the error code means.
Then, I just use trial and error to try to isolate the location in code that's failing, and the root cause of the failure.
If you just want a really quick way to find out what the error code means, you could use the "Error Lookup" tool packaged with Visual Studio (details here). Enter the hex value, and it will give you the string describing that error code.
Of course, once you know that, you've still got to figure out why it's happening.
A good way to look up error (hresult) codes is HResult Plus or welt.exe (Windows Error Lookup Tool).
I use logging internally in the COM-classes to see what is going on. Also, once the COM-class is loaded by the executable, you can attach the VS debugger to it and debug the COM code with breakpoints, watches, and all that fun stuff.
COM objects don't throw exceptions. They return HRESULTs, most of which indicate a failure. So if you're looking for the equivalent of an exception stack trace, you're out of luck. You're going to have to walk through the code by hand and figure out what's going on.