Try-catch ends in debugging instance unresponsive when break point is set

The routine tries to load a xml file. In debug mode with a break is set in line 2 and then the routine is excecuted step by step.
a) terminates without error when a valid xml file is selected
b) shows spinning ball and becomes unresponsive when the file selection dialog’s ‘Cancel’ button has been pressed

It terminates without error when the file selection dialogs ‘Cancel’ button has ben pressed and NO break point has been set.

If something is with wrong with the code, I’d expect a debug error message for case b), which is not shown. I have to manually terminate the debug instance.

Test config:
Xojo 2022r1.1
MacBook Pro M1, macOS 12.4

My basic rule is to have as little code inside a try/catch as possible. Also I wouldn’t nest try/catch. Why do you think you need a try/catch for the dialog.showmodal? You either get Nil back or a folderitem.

Good point. I was following documentation and webinars. Xojo beginner’s code, to say. But why is it not a good idea to work with nested try-catch?

What bugs me with this code is that file being Nil is not an issue by itself. How would this code behave if file is Nil, since there is no else to the if on line 9 ?

The Catch block starting on line 19 will not execute if file is Nill. I would first invoke dialog.Show modal. Then if file is Nil, I would display a message to the user. Once file is fine, the a Try Catch block would be useful if reading the file would go wrong.

Hi Gilles
tried what you suggested:
Put file = dialog.ShowModal outside of the try-catch statement for NilObjectException. It yields the same debug instance lockup.
Your comment made me re-reading the documentation and there it is stated that unlike Exceptions, Try statements can be nested. For testing, I commented out the entire inner try-catch statement (see below). I still get the spinning ball when hitting the cancel button in the dialog.

I tried your code, and it looks like an exception is being encountered in the framework on line 12. This causes the debug to pause twice, showing the beachball that you’re seeing in the app. Pressing Resume in the IDE will continue execution and you’ll eventually hit the Try…Catch for XmlException seen in my code below. I’ll open a case for this momentarily.

Here’s the code I’m using to reproduce the issue:

var xml as new XmlDocument
var file as FolderItem
var dialog as new OpenFileDialog

  file = dialog.ShowModal
  xml.LoadXml( file )
catch x_error as XmlException
  MessageBox( "Unable to load XML Document" )
catch f_error as NilObjectException
  MessageBox( "File not available" )
End Try

And this code will avoid the exception in the framework:

var xml as new XmlDocument
var file as FolderItem
var dialog as new OpenFileDialog

file = dialog.ShowModal
if file <> nil and file.Exists then
    xml.LoadXml( file )
  catch x_error as XmlException
    MessageBox( "Unable to load XML Document" )
  End Try
  MessageBox( "File not available" )
end if

EDIT: Xojo: Account Login

Thank you @Anthony_G_Cyphers,
Your code gets around it and I learned that a spinning ball in debug mode can be recovered - at least in this case.

1 Like

Happy to help!

Well I didn’t know whether it worked or not. Typically I only put a Try around one statement (a statement that may provoke an exception, of course). If there are more, then you don’t know which one caused the exception, if it occurs.

And then Return. I’m a great believer in early exit from a method if an error condition occurs. Handle it and get out, is my motto. Then subsequent code is simpler.

1 Like

But the only Try block runs

file = dialog.ShowModal

and if there is an exception, only theNilObjectException will be catch. If another exception is raised, then you will get a UnhandledException.

Exception handling can be tricky. When I code, I usually catch all exceptions, and then debugging will help me learn the exceptions I may encounter - there are some I may not think about. Then I may have many Catch blocks, one per exception type.

When debugging it’s important to see the application Window because it may wait for inputs and when for example a dialog is displayed because of an UnhandledException, you think the app is frozen, but it wait for the user to click Ok !

There are at least three ways to “handle” exceptions:
• be prepared against it (if f<>nil then) so no exception happens
• have a try/catch block
• implement the app.UnhandledException event

For the first two, it seems there are different opinions in this thread. Some prefer to foresee (if f<>nil then DoNotDoThat) while others seem to have no check at all and just let a Try/catch block handle any possible error “blindly”.
I recognise both methods kind of work, but is it just me who thinks the blind way should be avoided?

Absolutely agree with catching errors when and where they happen and being specific in how they are handled.
In this particular case, I’d like to differentiate between the cancel event triggered by the user and an IO exception (i.e. no access right for file to open). For the cancel event there is no further handling required but an IO error must be dealt with.
Is ‘Error ioerr As IOException’ the way to go?

Thanks @Gilles_Plante,
Agree, exceptions must be caught and handled. Need to learn how to produce clean exception handling code in Xojo :slight_smile:

Those are different cases.
To figure out whether the user has cancelled the OpenDialog, just check for file<>nil.
And to find out an exception, the try/catch block is the way to go.

I’d like to point out that you can’t have file=nil if the user has successfully chosen a file. If there’s a problem like not enough permission, either of those cases apply:
1: the user can’t choose the file in the OpenDialog. In this case, (s)he can either cancel or choose another file.
2: the user could choose the file (so the call returns a non-nil, valid file). Here, it’s when you attempt to load the file that it would fail (so the exception comes into play).


Since exceptions are expensive, it’s always a good idea to check what you can before attempting an action that could throw an exception. File<> nil, File.IsReadable, etc.