From claude-vb6-skills
Applies the CSEH (Code Style for Error Handler) pattern when adding or editing error handling in Visual Basic 6 procedures. Covers the structured On Error GoTo template with EhHeader/EhFooter regions, two CSEH styles (ErrRaise for utility functions that propagate to callers, and MsgBox for top-level UI procedures), line numbering (starting at 100, increments of 5) to enable Erl in error handlers, structured re-raise via Err.Raise with vbObjectError offset and qualified source string in App.Module.Procedure format, error message format including Err.Number, Err.Description and Erl, cleanup-before-raise discipline, and the legitimate use of On Error Resume Next strictly limited to cleanup and dispose routines. Activates whenever modifying VB6 procedures that have or need On Error handlers, the CSEH marker comment, numbered code lines, Err.Raise calls, or any discussion of error propagation, error logging, or fault tolerance in VB6.
How this skill is triggered — by the user, by Claude, or both
Slash command
/claude-vb6-skills:vb6-error-handlingThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
VB6 has no `try`/`catch`. The model is `On Error GoTo <label>` with structured
VB6 has no try/catch. The model is On Error GoTo <label> with structured
cleanup. The CSEH (Code Style for Error Handler) convention standardizes
this pattern across the codebase so error paths are predictable, log output is
consistent, and Erl (error line) is meaningful in production logs.
CSEH style is declared by a marker comment above the procedure signature:
'CSEH: ErrRaise
Public Function GetActiveCustomer(...) As Object
The <EhHeader> and <EhFooter> tags delimit regions that may be regenerated
by external tooling (MZ-Tools or similar). Never alter the delimiter format
or remove the tags — automation depends on them.
| Style | Marker | Handler behavior | Use for |
|---|---|---|---|
ErrRaise | 'CSEH: ErrRaise | Re-raises with Err.Raise vbObjectError + <offset>, ..., msg | Utility functions, library routines, any procedure called by other code |
MsgBox | 'CSEH: MsgBox | Displays critical dialog and returns to caller without re-raising | Top-level UI event handlers, command buttons, menu items |
Default for new code: ErrRaise. The MsgBox style is reserved for the
outermost layer (event handlers) where errors must be surfaced to the user and
the call stack ends.
Canonical structure for a function that propagates errors to its caller:
'CSEH: ErrRaise
Public Function GetActiveCustomer(ByVal lngCustomerID As Long) As Object
'<EhHeader>
On Error GoTo GetActiveCustomer_Err
EnterMethod "modDB", "GetActiveCustomer"
'</EhHeader>
Dim objCmd As Object
Dim objRs As Object
Dim strSQL As String
100 InitializeDBConnection
105 Set objCmd = CreateObject("ADODB.Command")
110 Set objCmd.ActiveConnection = mobjCnn
115 objCmd.CommandType = adCmdText
120 strSQL = "SELECT * FROM Customer WHERE idCustomer = ? AND custActive = 1"
125 objCmd.CommandText = strSQL
130 objCmd.Parameters.Append objCmd.CreateParameter("idCustomer", adInteger, adParamInput, , lngCustomerID)
135 Set objRs = objCmd.Execute
140 Set GetActiveCustomer = objRs
'<EhFooter>
On Error GoTo 0
GetActiveCustomer_Exit:
Set objCmd = Nothing
ExitMethod "modDB", "GetActiveCustomer"
Exit Function
GetActiveCustomer_Err:
Dim sGetActiveCustomer_Err As String
sGetActiveCustomer_Err = "Error: " & Err.Number & " - " & Err.Description & " (" & Erl & ")"
' clean up resources here
Set objCmd = Nothing
Set objRs = Nothing
ExitMethod "modDB", "GetActiveCustomer"
Err.Raise vbObjectError + 100, "SampleApp.modDB.GetActiveCustomer", sGetActiveCustomer_Err
'</EhFooter>
End Function
'CSEH: ErrRaise<EhHeader> region contains exactly On Error GoTo <Func>_Err and
EnterMethod "<module>", "<Func>"<Func>_Exit (success path)<Func>_Err (error path)<Func>_Exit falls through to Exit Sub/Exit Function — never to the
_Err label"Error: " & Err.Number & " - " & Err.Description & " (" & Erl & ")"Set ... = Nothing happens before
Err.Raise, not after (after is unreachable)ExitMethod is called on both paths — success and error — to keep the
trace stack consistentErr.Raise source: qualified as <Application>.<Module>.<Procedure>Err.Raise number: vbObjectError + <offset>, where <offset> is
chosen per procedure (see section 5)For top-level procedures where errors terminate at the UI:
'CSEH: MsgBox
Public Sub cmdSave_Click()
'<EhHeader>
On Error GoTo cmdSave_Click_Err
EnterMethod "frmCustomer", "cmdSave_Click"
'</EhHeader>
' ... UI logic that calls other CSEH:ErrRaise functions ...
'<EhFooter>
cmdSave_Click_Exit:
ExitMethod "frmCustomer", "cmdSave_Click"
Exit Sub
cmdSave_Click_Err:
Dim scmdSave_Click_Err As String
scmdSave_Click_Err = Err.Description & vbCrLf & _
"in SampleApp.frmCustomer.cmdSave_Click at line " & Erl
MsgBoxCritical scmdSave_Click_Err
GoTo cmdSave_Click_Exit
'</EhFooter>
End Sub
MsgBoxCritical (or equivalent project wrapper) displays the error to the
userErr.Raise at the end — the error stops hereGoTo <Func>_Exit after the dialog so cleanup and ExitMethod still runErl is a built-in function returning the line number where the last error
occurred — but only if lines are numbered. Without numbering, Erl returns 0
and traceability is lost.
Dim, no comments, no labels, no
<EhHeader>/<EhFooter> tags) Dim strSQL As String
100 strSQL = ""
105 strSQL = strSQL & "SELECT idCustomer, custName " & vbNewLine
110 strSQL = strSQL & " FROM Customer " & vbNewLine
115 strSQL = strSQL & " WHERE custActive = 1 " & vbNewLine
120 objCmd.CommandText = strSQL
125 Set objRs = objCmd.Execute
Number any procedure with:
On Error GoTo (CSEH style)Skip numbering for:
Get/Let that just reads/assigns a fieldThe error number passed to Err.Raise is vbObjectError + <offset>. The
offset is chosen per procedure (or per error category, if the codebase
catalogs them).
| Approach | Pattern |
|---|---|
| Per-procedure unique number | Each procedure gets its own offset |
| Per-category (validation, db, IO) | Range allocation (e.g., 100-199 validation, 200-299 db) |
| Fixed offset | Single offset across the codebase (less informative) |
In all cases, the qualified source string (SampleApp.modDB.GetActiveCustomer)
carries the procedure identity, so the offset is supplementary. Per-procedure
numbers help when an error code is logged without the message.
On Error Resume Next is forbidden in domain code. It silently swallows errors
and produces invisible failures. One legitimate exception: cleanup and
dispose routines, where the operation must complete even when individual steps
fail.
Public Sub CloseDBConnection()
On Error Resume Next ' OK: cleanup
If Not mobjCnn Is Nothing Then
If mobjCnn.State <> 0 Then mobjCnn.Close
End If
Set mobjCnn = Nothing
End Sub
Other acceptable uses:
Not acceptable:
Every CSEH procedure calls both:
EnterMethod "modDB", "GetActiveCustomer" ' in <EhHeader>
ExitMethod "modDB", "GetActiveCustomer" ' in both _Exit and _Err
Calling ExitMethod only on the success path leaves the trace stack with the
function "still open" after an error, corrupting future trace output. The
error label must also call ExitMethod before the Err.Raise.
See vb6-trace-pattern for the trace mechanism details.
Resource cleanup (Set objX = Nothing, closing recordsets, closing files)
appears in both the _Exit and _Err labels. Code paths must converge on
freed resources regardless of outcome.
Common pattern: extract cleanup into a helper or duplicate the lines in both
labels. The CSEH _Exit/_Err structure does not provide an automatic
finally — discipline is on the author.
| Anti-pattern | Why it breaks |
|---|---|
On Error Resume Next around a For loop with DB calls | Silently skips failed rows, produces partial state with no log |
Err.Raise without cleanup before it | Recordsets and connections leak |
ExitMethod only in _Exit | Trace stack grows monotonically; future traces are wrong |
Unnumbered procedure with Erl in the handler | Erl returns 0; production logs lose the line |
Empty Err.Description re-raised | Caller sees no message; first failure point is unidentifiable |
Missing Exit Sub/Exit Function before _Err label | Execution falls through into the error handler on success |
Modifying <EhHeader>/<EhFooter> tag format | Breaks regeneration tools (MZ-Tools or similar) |
'CSEH: ErrRaise or
'CSEH: MsgBox)<EhHeader> and <EhFooter> tags present and unmodifiedOn Error GoTo <Func>_Err is the first line inside <EhHeader>EnterMethod called in <EhHeader>_Exit and _Err labels exist_Exit falls through to Exit Sub/Exit Function, not into _ErrErr.Number, Err.Description, and ErlErr.Raise (or before MsgBoxCritical in
MsgBox style)ExitMethod is called in both labelsErr.Raise source string is <App>.<Module>.<Procedure>On Error Resume Next outside cleanup/disposenpx claudepluginhub alexcassol/claude-vb6-skills --plugin claude-vb6-skillsProvides behavioral guidelines to reduce common LLM coding mistakes, focusing on simplicity, surgical changes, assumption surfacing, and verifiable success criteria.
Searches, retrieves, and installs Agent Skills from prompts.chat registry using MCP tools like search_skills and get_skill. Activates for finding skills, browsing catalogs, or extending Claude.
Creates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.