It can be really frustrating when a Web agent has a LotusScript error. It is almost impossible to debug without the right information -- such basics as exactly where it occurred.
This standard piece of code should be at the top of every function or sub you have. It will push the error #, error line, and error text to the log, even for nested calls. With a minor tweak, it can also put the results in the Web browser, even for Web Query Save or Web Query Open. And it also works in any LotusScript, though it is most useful on the Web.
The idea: Every routine sure put together an error message when it gets an error. The message should consist of the name of the agent (or the name of the script library), followed by the name of the sub or function within the gaent/script library, with line number and specific error message following.
The routine should then "pass the error message" back to its caller, which can further pass it back up the line, until the final error is passed back from Initialize. At that point, Domino takes over and puts the error in the log. Because each routine adds its name, you can trace back the series of calls that led to the error, including line numbers at each step.
The first thing we need to do is make sure the log identifies where the error was generated. A global constant is used. Then, each sub/function must define its own label as well (since script provides us know way of knowing the name of the routine we are curreently in). A global declaration serves as a "backup" in case you forget to define it in any particular routine.
'Put this in every declaration section, changing the first (bit not the second) declaration to have the name of the design element that contains it; do not change the other CONST, and do not place the DIM in any routine, only in (Declarations) -- it must be global:
Private Const ErrRoutineGlobalPrefix = "SendCombinedNotifications" Const
ErrRoutineLocalPrefix = "UnknownRoutine" Dim ErrRoutineErrMessage As String
Add this line to the top of ever sub or function, including Initialize:
Const ErrRoutineLocalPrefix = 'put in the name of the sub or function here, in quotes.
For Initialize, make sure it is spelled exactly "Initialize" with capital I and the rest lower-case.
Add the following section immediately below:
On Error Goto PrintError Goto SkipErrorSection PrintError: Dim ErrRoutineErrMessage As String ErrRoutineErrMessage = ErrRoutineGlobalPrefix & "." & ErrRoutineLocalPrefix
& " error " & Err & " on line " & Erl & ": " & Error If ErrRoutineLocalPrefix = "Initialize" Then Print ErrRoutineErrMessage REM For WebQueryOpen, helps to have something like
DocumentContext.LotusScriptErrorMessageField = ErrRoutineErrMessage End If Error Err , ErrRoutineErrMessage SkipErrorSection: REM Rest of your code goes here
The only real problem with this is that if the series of callbacks gets too long, the log will truncate it. You can adapt the routine by splitting up the print statement inside the IF. Note that the print only occurs if you are in the initialize routine. Otherwise, the message would be repeated as it gets built up in the call return sequence. It also allows you the flexibility of assuming that certain routines might return an error that is innocuous, and you want to continue in the caller routine's error handler, instead of just passing the error back further.
Finally, note that I suggest adding this routine at the top, while most programmers add the error routine at the bottom. This allows me to have the ON ERROR and the error handler itself in one place, instead of having to paste TWO "standard" pieces of code in every sub or function. It also allows me to define the CONST in the same place, at the top of the rouine, where I am more likely to notice it if I accidentally copied it in without changing the CONST.
Note: If you are still using 4.6 server, there is a bug that causes it to report the wrong line number. I have a fix for this. Below the ON ERROR, add:
Dim ErrRoutineOffset As Integer
Error 9999, "Setting error offset value for 4.6"
Below PrintError, add:
If Erl = 9999 Then ErrRoutineOffset = Erl : Resume Next
" on line " & Erl & ": " &
" on line " & Erl & "-" & ErrRoutineOffset & ": " &
Now, you will see the error line reported as two values with a minus between them. If you subtract the two values, that will be how many lines beneath the Error 9999 statement taht the error occured.
This was first published in September 2001