No Catch Generic Exception

ID

csharp.no_catch_generic_exception

Severity

high

Remediation Complexity

trivial

Remediation Risk

low

Remediation Effort

low

Resource

Reliability

Language

CSharp

Tags

CWE:396, reliability

Description

Reports catch blocks that catch the over-broad System.Exception (or its alias Exception/SystemException), as well as a bare catch with no type. Catching the generic exception swallows every error, including ones the code cannot meaningfully handle.

Rationale

A catch (Exception) traps everything — including programming errors and unexpected runtime failures that should propagate. The result is that genuine bugs are silently absorbed, the program limps on in an invalid state, and the failure surfaces far from its cause. Catch the specific exception types you know how to recover from.

Two shapes narrow the handling back down to specific exceptions and are not reported, whatever the declared catch type is:

  • An exception filter, catch (Exception ex) when (ex is IOException): the when condition decides what the clause actually handles, and everything else keeps propagating without ever entering the body.

  • A rethrow anywhere in the body — throw; or throw new Wrapped(ex), including as an expression such as a switch arm: the exception still propagates instead of being silently absorbed, so the breadth of the declared type stops mattering.

public class Importer
{
    public void Broken()
    {
        try
        {
            Import();
        }
        catch (Exception ex)      // FLAW — catches every error, hiding bugs
        {
            Log(ex);
        }
    }

    public void AlsoBroken()
    {
        try
        {
            Import();
        }
        catch                     // FLAW — bare catch traps everything too
        {
            Ignore();
        }
    }

    public void Filtered()
    {
        try
        {
            Import();
        }
        catch (Exception ex) when (ex is IOException)  // OK — narrowed by the filter
        {
            UseDefault(ex);
        }
    }

    public void Rethrown()
    {
        try
        {
            Import();
        }
        catch (Exception ex)      // OK — logged, but rethrown so nothing is swallowed
        {
            Log(ex);
            throw;
        }
    }

    public void Ok()
    {
        try
        {
            Import();
        }
        catch (FileNotFoundException ex)  // OK — a specific, recoverable exception type
        {
            UseDefault(ex);
        }
    }
}

Remediation

Replace the generic catch with one or more catch clauses for the specific exception types the code can handle. Let exceptions you cannot recover from propagate to a higher-level handler.