Preserve Stack Trace

ID

csharp.preserve_stack_trace

Severity

high

Remediation Complexity

trivial

Remediation Risk

low

Remediation Effort

low

Resource

Reliability

Language

CSharp

Tags

reliability

Description

Reports a throw new …​Exception(…​) inside a catch block that does not pass the caught exception to the new exception. Dropping the caught exception loses the original stack trace and makes the root cause much harder to find.

Rationale

A catch that wraps a failure in a new exception but forgets to forward the original as the innerException throws away the entire chain that led to the failure. The exception report then points only at the rethrow site, hiding where the problem really started.

public class Repository
{
    public void Broken()
    {
        try
        {
            Query();
        }
        catch (DbException ex)
        {
            throw new RepositoryException("query failed");   // FLAW — drops ex, original trace is lost
        }
    }

    public void Ok()
    {
        try
        {
            Query();
        }
        catch (DbException ex)
        {
            throw new RepositoryException("query failed", ex); // OK — forwards ex as the inner exception
        }
    }

    public void OkRethrow()
    {
        try
        {
            Query();
        }
        catch (DbException)
        {
            throw;                                            // OK — bare rethrow preserves the trace
        }
    }
}

Remediation

Pass the caught exception as the innerException constructor argument (throw new RepositoryException("query failed", ex);), or use a bare throw; to rethrow the original exception with its stack trace intact.