Catch block silently swallows the exception

ID

vbnet.correctness.empty_catch_block

Severity

high

Remediation Complexity

trivial

Remediation Risk

low

Remediation Effort

low

Resource

Error Handling

Language

VB.NET

Description

Reports a Catch clause whose body contains no statement at all, for the typed (Catch ex As IOException), the catch-all bare (Catch) and the Try …​ Catch …​ Finally forms. A clause holding only a comment is reported as well, since a comment does not handle anything. Clauses that log, return a fallback value, retry, rethrow with a bare Throw or wrap the exception are not reported.

Rationale

An empty Catch clause discards the exception and lets execution continue as if the guarded code had succeeded. Nothing is logged and nothing is signalled to the caller, so the failure leaves no trace anywhere: the record is not written, the file is not copied, the message is not sent, and the program carries on with data that is silently incomplete. The defect then surfaces far from its cause - as a missing row, a stale total or a corrupted document - and there is no log entry, no stack trace and no exception type to work back from, which makes it one of the hardest classes of defect to diagnose in production. It also hides unrelated failures such as OutOfMemoryException or a programming error inside the Try body.

The following code illustrates the pattern detected by this rule:

Public Sub Register(ByVal number As String, ByVal amount As Decimal)
    Try
        Using command As New SqlCommand("INSERT INTO invoice (number, amount) VALUES (@n, @a)", _connection)
            command.Parameters.AddWithValue("@n", number)
            command.Parameters.AddWithValue("@a", amount)
            command.ExecuteNonQuery()
        End Using
        ' FLAGGED: Catch block silently swallows the exception
    Catch ex As SqlException
    End Try
End Sub

Remediation

Handle the exception or let it propagate; never do neither. If the failure is recoverable, write the recovery into the clause - log the exception with its details, substitute a documented fallback value, or retry the operation. If the caller must know, rethrow with a bare Throw to keep the original stack trace, or wrap the exception in a domain-specific one (Throw New ImportException(message, ex)). If ignoring the exception genuinely is correct, say so explicitly by narrowing the clause to that exact type and logging at debug level, so the decision is visible in the code and in the log rather than implied by an empty block.

Configuration

This detector does not need any configuration.