Unexpected NilObjectException

I’ve had some unexpected exceptions happening lately on my major project, and am hoping that someone has suggestions for how they might be possible. (These exceptions are in the built app, not when running in the IDE, so I can’t reproduce them.)

Here’s a typical code snippet, the user is getting a NilObjectException where Erln=2. The listbox is a control on a window, this code is called after the window opens. The Erln values are just to help identify where errors are happening.

The only thing that could go nil is the listbox, right? Since the error doesn’t happen on the first line, then ChooseListbox should still exist on the second line. What could make it go nil? The window closing in the middle of this code executing?

Dim Erln as Integer
Dim x as integer

Erln=1
If ChooseListbox.ColumnCount>0 Then

Erln=2
For x=0 To ChooseListbox.LastColumnIndex

Erln=3
ChooseListbox.Column(x).UserResizable=False
Erln=4
ChooseListbox.ColumnSortDirection(x)=ListBox.SortNone
Erln=5
ChooseListbox.ColumnType(x)=Listbox.TypeNormal

Next

End If

Exception Err As RuntimeException
If Err IsA EndException Or Err IsA ThreadEndException Then
Raise err //Re-raise the exception
End If
ReportTheBug (CurrentMethodName, Erln)

One way to identify what is wrong is to use a try/catch block that handle any exception. When such an exception occurs, display the exception error number, the message, variables contents etc. Send those values to the Debug Log.

1 Like

If you move that set of codes into the Listbox Open Event, does the issue occurs ?

One thing I find confusing in your code is if, for whatever reason, LastColumnIndex returns 0, the loop won’t execute at all. In this case, if the exception occurs after the loop (if there’s more in the actual code), Erln would also equal 2. I’d suggest adding Erln=6 after the End If, in general.

Now, for the actual issue, it’s weird, indeed. Could it be a timing issue, where your window is being closed between Erln=1 and Erln=2, from another place?
(I’d hardly expect that, but it’s my most logical answer)

if this is in the opening of the ChooseListbox then use “Me.” (or “Self.” in case of a subclass) instead of “ChooseListbox.” see if that helps.

Yes, probably so the order of opening and creation of controls is important (but out of your hands). That’s why almost alwyas you want to use the events of the control itself and use “Me.” or in case of subclass “Self.” to refer to the object.

We created a super for Window that starts a Timer in the Open event with a Period = 1. That raises an AfterOpen event where a subclass can set up controls like this knowing that the Window has been fully formed.

One thing to try before changing any code is to open and close the Window as fast as you can. That exposed similar issues for us.

You could also use:

Timer.CallLater(0, AddressOf AfterOpen)
That should be called on the next event loop.

Yes, that’s how we do it. BUT we didn’t cancel the Timer in Close and that lead to problems when closed quickly. An easy fix, but not an obvious one.

Other than the lack of a try/catch block, that’s exactly what I’m doing. the Exception Err as Runtime Exception should be catching any exceptions. If the try/catch is essential, then I’d have to put try/catch blocks around every few lines of code everywhere in 600,000+ lines of code, which just isn’t feasible…:frowning:

Try…Catch is the correct way to catch for exceptions you are ready to handle.

All other exceptions should bubble to the App.UnhandledException event, so that they may be reported to you. You should always exit your application when an unhandled exception occurs, as you don’t know just how messed up the state has become.

Advice suggesting you catch all exceptions at the bottom of every method is bad advice, and makes debugging things intelligently more difficult.

1 Like

I don’t get how that code catches all exceptions.

I’m hesitant to link the documentation, because again, it’s a really bad way to handle errors. But that’s what an exception statement does. It’s like a try…catch for the whole method.

https://documentation.xojo.com/api/exceptions/exception.html#exception

There isn’t anything in the code other than what I posted, but I think your question exposed the true problem:

This is an API 1 app, but .LastColumnIndex is an API 1 property, while .ColumnCount is an API 2 property. So if .ColumnCount=0, then .LastColumnIndex would be -1, which makes ChooseListbox.Column(-1) nil.

Thank you!!!

3 Likes

You’re right! The hard part is there are about 600,000 lines of code, and many were written long before I knew better ways to do things… So for now anyway, it’s triage & rewrite as the bugs arise… Thank you!

Good catch; glad you found the issue!

1 Like