Error Handling in Rust
# CHAPTER 15
Error Handling in Rust
1. Chapter Introduction
In most languages, when something goes wrong (like a missing file or a database failure), the language throws an "Exception". If you forget to wrap it in atry/catch block, your server crashes.
Rust does not have Exceptions. Instead, Rust forces you to handle errors explicitly using the Type System. In this chapter, we will learn about the two types of errors in Rust: Unrecoverable errors (panic!) and Recoverable errors (the Result Enum).
2. Learning Objectives
By the end of this chapter, you will be able to:-
Understand when a program should
panic!.
-
Understand the
Result<T, E>enum for recoverable errors.
-
Extract successful data or error messages using
match.
-
Use
unwrap()andexpect()responsibly.
-
Propagate errors up the call stack gracefully using the
?operator.
3. Unrecoverable Errors (panic!)
Sometimes, a bug is so severe that the program is in an invalid state and must be stopped immediately (e.g., trying to access an array out of bounds). In Rust, this triggers a Panic.
You can trigger a panic manually using the panic! macro:
When a panic occurs, Rust cleans up memory, prints the error message, and shuts down the application.
4. Recoverable Errors (Result Enum)
Most errors are not catastrophic. If a user tries to open a file that doesn't exist, we don't want to crash the server; we want to create the file or show a warning.
For this, Rust uses the Result Enum.
Let's attempt to open a file. The File::open function returns a Result.
5. Shortcuts: unwrap() and expect()
Writing a match statement every time is tedious. Rust provides shortcut methods on the Result type.
-
unwrap(): If the result isOk, it returns the value inside. If the result isErr, it callspanic!automatically for you.
-
expect("msg"): Exactly likeunwrap, but lets you provide a custom panic message.
*Rule of thumb: Only use unwrap or expect during prototyping, or when you are 100% mathematically certain the operation will not fail.*
6. Error Propagation (The ? Operator)
If you are writing a function that opens a file, reads it, and returns the text, you probably don't want to handle the error *inside* the function. You want to pass the error back to the caller so they can decide what to do. This is called Propagating the error.
Instead of writing massive match statements to return errors early, Rust provides the glorious ? operator.
The ? operator eliminates almost all boilerplate error checking code!
7. Mini Project: Safe File Reader
8. Common Mistakes
-
Using
?insidemain(): By default,main()returns an empty tuple(). The?operator requires the function to return aResult. If you use?inmain(), it won't compile unless you change the signature ofmaintofn main() -> Result<(), Box<dyn std::error::Error>>.
-
Overusing
unwrap(): In a production server, usingunwrap()is dangerous because any missing file or bad network connection will crash the entire server instance.
9. Best Practices
-
Embrace
?: Use the?operator extensively to keep your functions clean and push error handling to the top level of your architecture.
10. Exercises
-
1.
Write a function
divide(a: f64, b: f64) -> Result<f64, String>.
-
2.
If
bis 0.0, returnErr(String::from("Cannot divide by zero")). Otherwise, returnOk(a / b).
-
3.
In
main, call the function inside amatchstatement and print either the result or the error string.
11. MCQs with Answers
Q1. Does Rust use try/catch Exceptions?
a) Yes b) No, it uses the Type System (Result Enum) to handle errors
Answer: b) No, it uses the Type System.
What macro is used to deliberately crash a program in an unrecoverable state?
What are the two variants of the Result<T, E> Enum?
What does the .unwrap() method do on a Result?
How is .expect("msg") different from .unwrap()?
What does the ? operator do when placed after a function that returns a Result?
? operator in a function that does NOT return a Result or Option?
a) Yes b) No, the compiler will throw an error
Answer: b) No, the compiler will throw an error.
Why is Rust's approach to error handling considered safer than Exceptions?
If File::open fails, what variant of the Result enum does it return?
In a high-traffic production web server, what method should you almost NEVER use when processing user data?
12. Interview Questions
-
Q: Contrast the
Optionenum with theResultenum. When do you use each? (Answer:Optionis for absence of data,Resultis for the presence of an error).
-
Q: Explain how the
?operator reduces boilerplate code in error propagation.
13. Summary
Rust eliminates the uncertainty of Exceptions by forcing errors to be part of a function's return signature. By utilizing theResult enum, developers are compelled to acknowledge and handle potential failures. The brilliant ? operator ensures that this strictness does not result in bloated, unreadable code.
14. Next Chapter Recommendation
Our applications are getting large, and keeping everything inmain.rs is bad practice. In Chapter 16: Modules and Packages, we will learn how to split our code across multiple files, manage privacy (Public vs Private), and utilize the Cargo package manager to import third-party libraries.