Posted on by

FAQ Icon
It’s Wednesday and time for another frequently asked questions (FAQs) session. Here are some FAQs about Corona run-time errors.

1. My app was working fine and now I’m seeing a pop-up saying an error was found and my app quits. What changed?

Starting with build 2013.1030 on Android, run-time errors now display a pop-up alerting you to the problem and displaying information about the error. Previously, run-time errors were only displayed in the “adb logcat” window and may have gone undetected. We added the pop-ups so we could deal with run-time errors that could occur after we removed the default Android permissions. Currently, the iOS builds don’t support this feature.

2. I don’t remember getting these errors before. Are these real errors?

Yes, if you are getting a run-time error, it’s because an exception occurred and your program failed to execute the code after the error. Your app may have been getting errors all along, but either you were not looking for them, they occurred only once in a while, or they only occurred on devices that you did not test.

Generally these errors occur because of nil values returned by an API, and the value is later used to do something. One example is trying to remove a Corona object when the object pointer is nil. Another is displaying a text string that is concatenating a string with a returned value that was nil. The general cause is a programming mistake where the variable/object is “out of scope” in the function that is trying to use it or not checking for a nil value after calling a function.

Here is one example:

local touchRect = display.newRoundedRect( 0, 50, 70, 30, 10 )
touchRect.x = display.contentCenterX

local count1 = 0
local count2 = 0
local count3 = 0
        
function touchRect:touch( event )
    if event.phase == "ended" then
        count1 = count1 + 1
        count2 = count2 + 1
        count3 = count3 + 1

        text1.text = "Count1 = " .. count1
        text2.text = "Count2 = " .. count2    -- << error here
        text3.text = "Count3 = " .. count3        
    end
    
    return true
end

text1 = display.newText( "Count1 = 0", 10, 100, native.systemFont, 20 )
local text2 = display.newText( "Count2 = 0", 10, 140, native.systemFont, 20 )
text3 = display.newText( "Count3 = 0", 10, 170, native.systemFont, 20 )

touchRect:addEventListener( "touch" )
Screen Shot of Sample Code

Tapping on the white rectangle causes all three counts to increment by one and display the updated counts. There is a bug that causes an error when "text2.text" is set. The error: "attempt to index global 'text2' (a nil value)", is because text2 is defined as a local variable and was defined after the touch function. It's out of scope to the function and is nil.

If you run the above code in the simulator and tap on the rectangle, you will see the first counter increments but not the other two. The reason is the chunk of code aborts right after trying to set text2.text -- the remaining code never executes. You can keep tapping the rectangle and the first counter keeps incrementing. To the person using the app, it looks like the program is running fine if they didn't know the other two counters should increment too.

The changes we made to the Android code will detect this run-time error and display a pop-up with the file and line number of the error. You may think that your app was running fine before, but if your code has run-time errors, the portion of your code after the errors were not really executing. It should be noted that errors like this will be detected in all platforms and displayed on the console. You must have a console window open in order to see it it (Xcode for iOS or "adb logcat" for Android).

The above error can be easily fixed by either by defining text2 before the function definition or removing "local" where text2 is defined:

text2 = display.newText( "Count2 = 0", 10, 140, native.systemFont, 20 )

3. How do I keep the pop-up from happening when I release my app to Google Play?

Currently, there are two ways to avoid the pop-up: 1) find all bugs and fix them (as shown above), or 2) add a pcall statement to areas of your code that you know could cause problems.

We understand that it's not possible to find and kill all the bugs in an app so we are planning to add a run-time listener that will trap errors and allow the program to decide how to deal with them. If you build an app for the App Store and a user runs across an error, you could log the error and send it back to your servers for evaluation or simply ignore it. This feature is not available now, but should be in a future Daily Build soon.

4. Is there any way to trap the errors myself and not have it quit the app or display a pop-up to the user?

Besides waiting for a Daily Build with the new run-time error listener, you can wrap pieces of your code in a Lua pcall statement to trap errors. The pcall (protected call) can be used to call any function or method, with the call returning the execution status. It returns true if the call executed correctly, and false if it failed because of a run-time error. Since it traps the run-time error, it avoids the pop-up and doesn't quit the app. There is a slight performance overhead using pcall, so it should only be used where you need to deal with errors that may occur outside the control of the app (e.g., network calls).

The syntax of pcall is:

pcall( f [, ...] )

where f is the function to be called,
and ... is the arguments for the function.

For the sake of this exercise I wrapped setting text2 in a function (setText2) and called it using pcall. The results of the call is stored in status and displayed.

local touchRect = display.newRoundedRect( 0, 50, 70, 30, 10 )
touchRect.x = display.contentCenterX

local count1 = 0
local count2 = 0
local count3 = 0

local function setText2( value )
    text2.text = "Count2 = " .. value
end
        
function touchRect:touch( event )
    if event.phase == "ended" then
        count1 = count1 + 1
        count2 = count2 + 1
        count3 = count3 + 1

        text1.text = "Count1 = " .. count1
        
        local status = pcall( setText2, count2 )
        print( "pcall status is ", status )
        
        text3.text = "Count3 = " .. count3        
    end
    
    return true
end

text1 = display.newText( "Count1 = 0", 10, 100, native.systemFont, 20 )
local text2 = display.newText( "Count2 = 0", 10, 140, native.systemFont, 20 )
text3 = display.newText( "Count3 = 0", 10, 170, native.systemFont, 20 )

touchRect:addEventListener( "touch" )

When you run this modified code, the pcall status is false, indicating that a run-time error occurred. Since both counters 1 and 3 increment, this shows that the pcall trapped the run-time error and allowed the remaining code to execute.

The pcall is only useful where you expect your code could fail and need to guard against it or test for the failed condition.

5. Why is the error pop-up only in Android builds?

We made the change first in Android because we needed a way to deal with the errors that could occur when we removed the default permissions in the Android builds. We feel detecting and trapping errors is a useful thing for our developers, and plan to add this feature to iOS as well as the Mac and Windows simulator in an upcoming Daily Build.

In the current release and Daily builds, we do provide run-time error information that can help you find bugs in your apps. If you do a developer build, you will see the file, line number, and the type of error in the console. Release builds (for the App Store) will only show the type of error encountered.

As an added note, if you are using the Mac Simulator, be sure to start the Corona Terminal and not the Corona Simulator. The Corona Terminal loads a console window and then starts the Corona Simulator. The console window displays print, warning and error messages.

That's it for today's FAQs. I hope you enjoyed the post, and even learned a few things.


Posted by . Thanks for reading...

Post Category: FAQ

Post Tags:

7 Responses to “Wednesday FAQs: Corona Run-Time Errors”

  1. Vladimir

    “If you build an app for the App Store and a user runs across an error, you could log the error and send it back to your servers for evaluation or simply ignore it. This feature is not available now, but should be in a future Daily Build soon”

    This feature is for iOS only or will be an Android version also ?

    Reply
  2. Jeff

    > If you do a developer build, you will see the file, line number, and the type of error in the console. Release builds (for the App Store) will only show the type of error encountered.

    Is there a way to (optionally) include more debug information on App Store release builds? Right now we wrap most of our code in xpcalls and post all unhandled exceptions to our servers where we log the errors (along with device type, version, etc). We include the debug.traceback() along with the error but it’s a bit of a detective hunt to pin down the culprit using a data like this:

    ?:0: attempt to perform arithmetic on upvalue ‘?’ (a nil value)

    stack traceback:
    ?: in function
    ?: in function ‘destroy’
    ?: in function ‘?’
    ?: in function

    Many times we are able to work our way to the culprit but having the option to include the developer debug data on a release build to trap a nasty bug would be terrific.

    Thanks

    Reply
  3. Alex

    I read this faq and tried to put out of my mind just how ridiculous it was that this was implemented into daily builds without informing your users. However, I haven’t been successful. I have been chasing issues all day that relate to this, when just a week ago my beta testers were having zero problems with my builds.

    I realize that error-less code is the best way to keep the above from destroying my code and the good will of my beta testers, but as you said above, it is close to impossible to find and kill all bugs in an app, which is why beta testing exists.

    My question is, what benefit is this without the runtime error listener? My app ran fine without it before, even though it (apparently) was throwing runtime errors from time to time, but still ran rock solid. The above has caused me to do some serious code re-working, which is fine because obviously there were errors. However, the code was fine beforehand and the app ran as I intended. What possible outcome is this implementation meant to achieve?

    Reply
    • Tom Newman

      Alex,

      Daily builds are always a “work in progress.” They contain bug fixes and new features that we expose to our users to use and comment. We don’t always get it right and sometimes it takes a few iterations to fine tune features we add. With that said, we also don’t recommend that you release your product with daily builds without fully testing and debugging. The Daily Build notes do indicate changes made for that release. The notes are not intended to be complete documentation, but a quick idea about what changed.

      As for the change we made that pops up a message box on Android, we felt that was something that would help our users. Many times run-time errors occur and the programmer doesn’t realize that a error occurred, but notice something not working quit right in the app. Having an app throw a run-time error is not “rock solid” in my mind. Run-time errors cause the code chunk to abort, which means your app is not doing what you expect. Sometimes these run-time error may go unnoticed, but other times it could change the flow of the app or even cause it to crash. Again, not a “rock solid” experience.

      Adding a “error listener” is something that came up after we released the daily build (1030) and getting some feedback from users. It’s something that we’re working on and plan to implement sooner rather than later. We also mentioned using pcalls for area of your code that could generate run-time errors. The bottom line for removing run-time errors is testing and eliminating the reason for the run-time errors in the first place and not trying to trap and ignore the error.

      The benefit of having a pop-up message showing run-time errors is testing. Most apps go out to beta testers so they can report on errors they find. In the past, silent run-time errors may go unnoticed by the testers, but now they get the information and can report where things fail. Should the pop-up error be suppressed for release build is something we’ve debated internally. There are good arguments on both sides and we feel adding an “error listener” may be the best solution to let the programmer decide how it should be handled.

      A few years back we release new builds every three or four months and there were no daily builds. We felt it was better to get bug fixes and new features in the hands of our developers before a release build so we decided to offer our internal builds to developers to use and provide feedback about what we are doing right and wrong. Because of the daily build process, you can’t always depend on every daily build as a production-ready release.

      Reply
  4. Alex

    btw, I really do want to know the benefit, so I can take advantage of it. I’m not just trying to complain; I would very like to know the positives of this situation.

    Reply
  5. Bohumil

    I also cannot see any benefits. I was happy that finaly the default Android permissions were removed. I thought that we will be able simply to rebuild our Android apps which work OK and the customers will be happy. But it is not possible. There are always problems with some complex scenes and on some hardware. Our apps worked fine but now we should spend weeks of time with all our apps. I am not sure why this happened and what is the reason…

    Reply
  6. Daniel Williams

    I can see the direction you were trying to in to provide more information to developers, but I disagree with the approach. Instead of forcing the pop-ups, developers should have the option to enable or disable the pop-ups. My guess is that the majority of people using Corona are indie developers and we don’t always have access to the all the different devices.

    For a future build, can you give us the option to enable/disable pop-ups in the build.settings or config.lua file?

    Also, this is not a post bashing Corona’s approach, just some feedback. I still love what you provide us.

    Reply

Leave a Reply

  • (Will Not Be Published)