Dropped Exception

ID

csharp.dropped_exception

Severity

low

Remediation Complexity

trivial

Remediation Risk

low

Remediation Effort

low

Resource

Reliability

Language

CSharp

Tags

CWE:391, exception-handling, reliability

Description

Reports catch clauses whose body is non-empty yet silently discards the caught exception: the variable is never referenced, no throw statement re-raises the failure and no logger call is made.

Rationale

Swallowing an exception turns a recoverable, observable error into a ghost bug. The operator never learns that the operation failed; the tooling never records a stack trace; downstream code keeps running on inconsistent state. The catch block exists for control flow but loses every shred of diagnostic information the runtime tried to hand over.

Empty catch blocks are reported by a sister rule (csharp.empty_catch_block). This rule covers the more insidious case where the catch body looks busy but never acts on the exception itself.

public void LoadOk(string path)
{
    try { File.ReadAllText(path); }
    catch (IOException ex)                                          // FLAW — ex is never used
    {
        retries++;
        attempts.Add(path);
    }
}

public void LoadLogged(string path)
{
    try { File.ReadAllText(path); }
    catch (IOException ex)                                          // OK — logged
    {
        logger.LogError(ex, "load failed");
    }
}

public void LoadRethrow(string path)
{
    try { File.ReadAllText(path); }
    catch (IOException)                                             // OK — rethrows
    {
        Cleanup();
        throw;
    }
}

Remediation

Either log the exception (preserving the stack trace), re-throw with throw;, or wrap it in a domain-specific exception via throw new MyException("…​", inner). If the catch truly only needs the type and is followed by a throw;, omit the variable name to make the intent obvious.