Which built-in .NET exceptions can I throw from my application?
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
You can absolutely throw built-in .NET exceptions from your own code. The key is to choose the type that accurately describes the contract violation or invalid state that occurred, rather than picking an exception just because the name looks close enough.
Good Built-in Exceptions for Application Code
Several built-in exception types are designed for ordinary application-level validation and state checks.
Common examples include:
- '
ArgumentException' - '
ArgumentNullException' - '
ArgumentOutOfRangeException' - '
InvalidOperationException' - '
NotSupportedException' - '
ObjectDisposedException' - '
FormatException' - '
TimeoutException' - '
OperationCanceledException'
These are good candidates because their meanings are well understood across the .NET ecosystem.
Match the Exception to the Failure
The real question is not "what am I allowed to throw". It is "what failed, exactly?"
Use ArgumentNullException when the caller omitted a required argument.
Use InvalidOperationException when the method exists and the arguments are valid, but the object's current state makes the operation illegal.
That distinction makes error handling much easier for callers.
Exceptions You Usually Should Not Throw Manually
Some built-in exceptions are technically throwable but are usually the wrong semantic choice in application code.
Examples include:
- '
NullReferenceException' - '
IndexOutOfRangeException' - '
AccessViolationException' - '
StackOverflowException' - '
OutOfMemoryException'
Those exceptions typically represent runtime failures, corrupted process state, or CLR-level problems rather than cleanly designed application contracts.
For example, if an index parameter is invalid, throw ArgumentOutOfRangeException rather than manually throwing IndexOutOfRangeException.
When a Custom Exception Makes Sense
Custom exceptions are useful when the failure is domain-specific and built-in exception names are too generic. A payment workflow, scheduling engine, or business-rules subsystem may have errors that deserve first-class names.
Even then, do not overuse custom exceptions for routine validation. Most bad arguments and bad object states are already well covered by standard framework types.
A Simple Selection Rule
A practical rule set looks like this:
- If the caller passed a bad argument, use an
Argument*exception. - If the object is in the wrong state, use
InvalidOperationException. - If the operation is intentionally unsupported, use
NotSupportedException. - If the failure belongs to your business domain, consider a custom exception.
That covers most application code cleanly.
Common Pitfalls
A common mistake is manually throwing runtime-failure exceptions such as NullReferenceException or IndexOutOfRangeException because they sound familiar.
Another mistake is creating custom exceptions for simple argument validation, which makes APIs noisier without adding precision.
It is also easy to forget useful context. Argument-related exceptions should usually include the parameter name, and messages should explain what rule was violated.
Summary
- Throw built-in .NET exceptions when they accurately describe the problem.
- '
Argument*exceptions andInvalidOperationExceptionare common, appropriate choices.' - Avoid manually throwing exceptions that usually indicate runtime or CLR failures.
- Use custom exceptions only when the failure is genuinely domain-specific.
- Pick the exception type based on the contract that failed, not on naming convenience.

