100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
Programming

Error Handling with Try/Catch

Learn structured exception handling in VB.NET using Try, Catch, Finally, and Throw to write robust code that gracefully handles runtime errors.

Control Flow & ProceduresIntermediate10 min readJul 10, 2026
Analogies

The Try...Catch...End Try Block

VB.NET's structured exception handling wraps risky code in a Try block; if a runtime error occurs, execution immediately jumps to a matching Catch block instead of crashing the program, and the whole construct closes with End Try. A Catch block can specify an exception type, such as Catch ex As FormatException, to handle only that category of error, and multiple Catch blocks can be stacked to handle different exception types differently, evaluated in order from most specific to most general.

🏏

Cricket analogy: A team's rain-interruption protocol is like a Try block: they attempt to complete 50 overs, but if a Catch (Rain) event occurs, they immediately switch to the Duckworth-Lewis-Stern recalculation instead of continuing the original plan as if nothing happened.

Multiple Catch Blocks and the When Filter

Stacking several Catch clauses lets a Try block respond differently depending on what actually went wrong — for example Catch ex As DivideByZeroException before a more general Catch ex As Exception, since VB.NET evaluates Catch blocks in order and uses the first type match. A When clause adds a further Boolean condition to a Catch, such as Catch ex As IOException When ex.Message.Contains("locked"), so the block only activates when both the exception type matches and the extra condition is true, otherwise the search continues to the next Catch.

🏏

Cricket analogy: A team's contingency plan stacks specific responses: Catch a rain delay first with the DLS method, then Catch a floodlight failure with a different fallback, and only Catch any other general disruption with abandoning the match, checked in that specific order.

The Finally Block

A Finally block, placed after all Catch blocks, always executes whether or not an exception occurred and whether or not it was caught — making it the right place to release resources like file handles, database connections, or network sockets that must be cleaned up regardless of outcome. In modern VB.NET, a Using block is often preferable for IDisposable resources since it automatically calls the equivalent of a Dispose() cleanup in a Finally block, but Finally remains essential for other cleanup logic like resetting a UI state or logging that an operation completed.

🏏

Cricket analogy: Regardless of whether a match is won, lost, or abandoned due to rain, the ground staff's Finally-block task of covering the pitch and collecting the stumps happens every single time once play concludes, exception or not.

Throwing Exceptions and Custom Exception Types

The Throw statement raises an exception, either a built-in .NET type like Throw New ArgumentException("Invalid input") or a custom class inheriting from Exception, letting a procedure signal a specific failure condition to its caller rather than silently returning an invalid result. Custom exceptions, declared as Public Class InsufficientFundsException : Inherits Exception, let large applications distinguish domain-specific errors from generic ones in Catch blocks; this structured approach has fully replaced the legacy On Error Goto and On Error Resume Next statements from classic VB, which are still supported for compatibility but are discouraged in new VB.NET code.

🏏

Cricket analogy: A DRS system throws a specific InsufficientEvidenceException equivalent when ball-tracking data is unclear, rather than silently guessing, forcing the on-field umpire's original decision to stand rather than pretending certainty exists where none does.

vbnet
Module ErrorHandlingDemo
    Public Class InsufficientFundsException
        Inherits Exception

        Public Sub New(message As String)
            MyBase.New(message)
        End Sub
    End Class

    Sub Main()
        Try
            WithdrawFunds(500D, 200D)
        Catch ex As InsufficientFundsException
            Console.WriteLine($"Withdrawal failed: {ex.Message}")
        Catch ex As IOException When ex.Message.Contains("locked")
            Console.WriteLine("Account file is locked, try again later.")
        Catch ex As Exception
            Console.WriteLine($"Unexpected error: {ex.Message}")
        Finally
            Console.WriteLine("Transaction attempt logged.")
        End Try
    End Sub

    Sub WithdrawFunds(amount As Decimal, balance As Decimal)
        If amount > balance Then
            Throw New InsufficientFundsException(
                $"Cannot withdraw {amount:C} from a balance of {balance:C}")
        End If
        Console.WriteLine("Withdrawal successful.")
    End Sub
End Module

Use a Using block instead of a manual Try/Finally when working with any IDisposable resource, such as a StreamReader or SqlConnection — Using guarantees Dispose() is called even if an exception occurs, with less boilerplate than writing the Finally block yourself.

Avoid the legacy On Error Goto and On Error Resume Next statements in new VB.NET code. On Error Resume Next in particular silently swallows errors and lets execution continue with potentially invalid state, making bugs far harder to diagnose than with structured Try/Catch, which forces you to explicitly decide how each exception type is handled.

  • Try wraps risky code; Catch blocks handle specific exception types, evaluated in order from most specific to most general.
  • Multiple Catch blocks can target different exception types, and a When clause adds an extra Boolean condition to a Catch.
  • Finally always executes after a Try/Catch, whether or not an exception occurred, making it ideal for guaranteed cleanup.
  • Using blocks are preferred over manual Finally blocks for IDisposable resources like file streams and database connections.
  • Throw raises an exception, either a built-in .NET type or a custom class inheriting from Exception.
  • Custom exception classes let large applications distinguish domain-specific failures from generic runtime errors in Catch blocks.
  • Legacy On Error Goto and On Error Resume Next are discouraged in favor of structured Try/Catch/Finally.

Practice what you learned

Was this page helpful?

Topics covered

#Programming#VBNETStudyNotes#ErrorHandlingWithTryCatch#Error#Handling#Try#Catch#ErrorHandling#StudyNotes#SkillVeris