Edit

Share via


CA1031: Do not catch general exception types

Property Value
Rule ID CA1031
Title Do not catch general exception types
Category Design
Fix is breaking or non-breaking Non-breaking
Enabled by default in .NET 9 No

Cause

A general exception such as System.Exception or System.SystemException is caught in a catch statement, or a general catch clause such as catch() is used.

By default, this rule only flags general exception types being caught, but this is configurable.

Rule description

General exceptions should not be caught.

How to fix violations

To fix a violation of this rule, catch a more specific exception, or rethrow the general exception as the last statement in the catch block.

When to suppress warnings

Do not suppress a warning from this rule. Catching general exception types can hide run-time problems from the library user and can make debugging more difficult.

Note

Starting with .NET Framework 4, the common language runtime (CLR) no longer delivers corrupted state exceptions that occur in the operating system and managed code, such as access violations in Windows, to be handled by managed code. If you want to compile an application in .NET Framework 4 or later versions and maintain handling of corrupted state exceptions, you can apply the HandleProcessCorruptedStateExceptionsAttribute attribute to the method that handles the corrupted state exception.

Configure code to analyze

Use the following option to configure which parts of your codebase to run this rule on.

You can configure this option for just this rule, for all rules it applies to, or for all rules in this category (Design) that it applies to. For more information, see Code quality rule configuration options.

Disallowed exception type names

You can configure which exception types are disallowed from being caught. For example, to specify that the rule should flag catch handlers with NullReferenceException, add the following key-value pair to an .editorconfig file in your project:

dotnet_code_quality.CA1031.disallowed_symbol_names = NullReferenceException

Allowed type name formats in the option value (separated by |):

  • Type name only (includes all symbols with the name, regardless of the containing type or namespace)
  • Fully qualified names in the symbol's documentation ID format with a T: prefix.

Examples:

Option value Summary
dotnet_code_quality.CA1031.disallowed_symbol_names = ExceptionType Matches all symbols named 'ExceptionType' in the compilation.
dotnet_code_quality.CA1031.disallowed_symbol_names = ExceptionType1|ExceptionType2 Matches all symbols named either 'ExceptionType1' or 'ExceptionType2' in the compilation.
dotnet_code_quality.CA1031.disallowed_symbol_names = T:NS.ExceptionType Matches specific types named 'ExceptionType' with given fully qualified name.
dotnet_code_quality.CA1031.disallowed_symbol_names = T:NS1.ExceptionType1|T:NS1.ExceptionType2 Matches types named 'ExceptionType1' and 'ExceptionType2' with respective fully qualified names.

You can configure these options for just this rule, for all rules it applies to, or for all rules in this category (Design) that it applies to. For more information, see Code quality rule configuration options.

Example

The following example shows a type that violates this rule and a type that correctly implements the catch block.

// Creates two violations of the rule.
public class GenericExceptionsCaught
{
    FileStream? inStream;
    FileStream? outStream;

    public GenericExceptionsCaught(string inFile, string outFile)
    {
        try
        {
            inStream = File.Open(inFile, FileMode.Open);
        }
        catch (SystemException)
        {
            Console.WriteLine("Unable to open {0}.", inFile);
        }

        try
        {
            outStream = File.Open(outFile, FileMode.Open);
        }
        catch
        {
            Console.WriteLine("Unable to open {0}.", outFile);
        }
    }
}

public class GenericExceptionsCaughtFixed
{
    FileStream? inStream;
    FileStream outStream;

    public GenericExceptionsCaughtFixed(string inFile, string outFile)
    {
        try
        {
            inStream = File.Open(inFile, FileMode.Open);
        }

        // Fix the first violation by catching a specific exception.
        catch (FileNotFoundException)
        {
            Console.WriteLine("Unable to open {0}.", inFile);
        };

        // For functionally equivalent code, also catch 
        // remaining exceptions that may be thrown by File.Open

        try
        {
            outStream = File.Open(outFile, FileMode.Open);
        }

        // Fix the second violation by rethrowing the generic 
        // exception at the end of the catch block.
        catch
        {
            Console.WriteLine("Unable to open {0}.", outFile);
            throw;
        }
    }
}

CA2200: Rethrow to preserve stack details