Error System
Source: source/function/errsysw.prg
FiveWin replaces Harbour's default error handler with a GUI-based error dialog that displays
detailed diagnostic information. The error system is automatically initialized at application
startup via the ErrorSys() procedure, which sets an error block calling
ErrorDialog().
Error Handling Flow
silently] B -->|Network Open Error| D[Set NetErr .T.
Return .F.] B -->|Append Lock Error| E[Set NetErr .T.
Return .F.] B -->|Other Error| F[ErrorDialog] F --> G[Build Error Log] G --> H{bUserDlg set?} H -->|Yes| I[Call Custom Dialog] H -->|No| J[Show FWH Error Dialog] J --> K[User Chooses Action] K -->|Quit| L[Write error.log
QUIT] K -->|Retry| M[Return .T.] K -->|Default| N[Return .F.] K -->|Debug| O[AltD at error] L --> P{bUserAction set?} P -->|Yes| Q[Execute Post-Error Action] P -->|No| R[Application Exits]
Automatic Error Handling
Certain error types are handled automatically without showing the error dialog:
| Error | genCode | Automatic Action |
|---|---|---|
| Division by zero | EG_ZERODIV | Returns 0 silently |
| Network open error (OS code 32 or 5) | EG_OPEN | Sets NetErr(.T.), returns .F. |
| Append lock error | EG_APPENDLOCK | Sets NetErr(.T.), returns .F. |
| Recursive error (7+ levels deep) | any | Forces QUIT to prevent infinite loop |
Error Dialog
The FiveWin error dialog is a modern, feature-rich dialog that adapts to the system theme:
- Dark mode auto-detection -- the dialog reads the Windows "AppsUseLightTheme" registry key and adjusts its color scheme accordingly
- Error message -- displayed prominently at the top
- Call stack -- shown in a listbox with procedure names, line numbers, and source files
- Action buttons:
- Quit -- writes error.log and terminates
- Retry -- returns .T. (if
e:canRetry) - Default -- returns .F. (if
e:canDefault) - Debug -- activates the debugger (if available)
- Copy button -- copies the complete error log to the clipboard
- See button -- opens error.log in Notepad
Error Log Format
When the user clicks "Quit", an error.log file is written (or appended). The log contains these sections:
Application
===========
Path and name: C:\myapp\myapp.exe (32 bits)
FiveWin version: FWH 26.05
Harbour version: 3.2.0
Date: 2026-03-24
Time: 14:30:45
Error
=====
Description: Argument error
SubSystem: BASE
Operation: +
Args:
[1] = C "Hello"
[2] = N 42
Call Stack
==========
Called from MAIN(25) in source\main.prg
Called from PROCESSDATA(102) in source\process.prg
...
System
======
OS: Windows 11 Build 22621
Windows Directories
Active tasks
Databases in use
================
Area 1: CUSTOMERS (customers.dbf) RecNo: 42 RecCount: 1500
...
Customizing the Error System
SetErrorPath() / SetErrorFileName()
// Change error log location
SetErrorPath( "C:\logs\" )
SetErrorFileName( "myapp_error.log" )
SetErrorDialog() -- Custom Dialog
// Replace the entire error dialog with a custom one
SetErrorDialog( { |oDlg, e, cLog, aStack|
// oDlg is the dialog being created
// e is the error object
// cLog is the error log text
// aStack is the call stack array
// Return: nil (use default buttons) or handle buttons yourself
} )
SetPostErrorAction() -- Post-Error Hook
// Execute code after the error dialog closes
SetPostErrorAction( { |e, cLog|
// Send error report to server
SendErrorReport( cLog )
// or restart the application
// WinExec( GetModuleFileName( GetInstance() ) )
} )
Custom ErrorBlock
// Replace the error handler entirely
ErrorBlock( { |e| MyErrorHandler( e ) } )
static function MyErrorHandler( e )
// Log to file
LogFile( "errors.log", { e:Description, e:Operation, ;
ProcName(4), ProcLine(4) } )
// Show simple message
MsgStop( e:Description + CRLF + ;
"at " + ProcName(4) + "(" + LTrim( Str( ProcLine(4) ) ) + ")" )
// Quit the application
PostQuitMessage( 0 )
__Quit()
return nil
Example: TRY/CATCH Blocks
#include "FiveWin.ch"
function Main()
local xResult
// TRY/CATCH prevents the error dialog from showing
TRY
xResult := SomeRiskyOperation()
MsgInfo( "Result: " + cValToChar( xResult ) )
CATCH e
MsgAlert( "Error: " + e:Description + CRLF + ;
"Operation: " + e:Operation )
END
return nil
Example: Custom Error Handler with Email
#include "FiveWin.ch"
function Main()
// Install custom post-error action
SetPostErrorAction( { |e, cLog|
// Save error log
MemoWrit( "crash_" + DToS( Date() ) + "_" + StrTran( Time(), ":", "" ) + ".log", cLog )
// Could send email notification here
// SendMail( "admin@company.com", "App Crash", cLog )
} )
// Change error log location
SetErrorPath( "C:\logs\" )
SetErrorFileName( "app_errors.log" )
// ... rest of application ...
AppMain()
return nil
Error Object Properties
The error object e passed to the error handler is a standard Harbour Error object:
| Property | Type | Description |
|---|---|---|
e:Description | Character | Human-readable error description |
e:Operation | Character | The operation that caused the error |
e:SubSystem | Character | Subsystem name (BASE, DBCMD, etc.) |
e:genCode | Numeric | Generic error code (EG_*) |
e:subCode | Numeric | Subsystem-specific error code |
e:osCode | Numeric | Operating system error code |
e:Args | Array | Arguments that caused the error |
e:canRetry | Logical | Whether retry is possible |
e:canDefault | Logical | Whether default action is possible |
e:canSubstitute | Logical | Whether a substitute value can be returned |
e:FileName | Character | File that caused the error (if applicable) |
Multi-Language Support
The error dialog uses FWString() for all user-visible text, so it automatically
adapts to the language set by FWSetLanguage(). Supported strings include
"Application", "Path and name", "Date", "Time", error descriptions, and button labels.