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.