🚫 No Unwrap!

Why Rust's expect() is Superior to unwrap()

The Problem with unwrap()

Rust's unwrap() method is a silent killer in your codebase. When it panics, you're left with cryptic error messages that provide no context about why the failure occurred or where in your logic things went wrong. Rust is about human-first errors, ane we should be better about this!

let value = some_option.unwrap(); // 💥 Panic: "called `Option::unwrap()` on a `None` value"

This tells us nothing about the business logic failure that led to this panic!

The expect() Solution

The expect() method does everything unwrap() does, but with one crucial improvement: it lets you provide meaningful context when things go wrong.

let user_id = session.get_user_id()
    .expect("User must be logged in to access dashboard");

Now when this panics, you get: "User must be logged in to access dashboard" - immediately actionable information!

Side-by-Side Comparison

❌ unwrap()

  • Generic panic messages
  • No context about business logic
  • Debugging nightmare
  • Poor developer experience
  • Lazy programming practice

✅ expect()

  • Custom, meaningful error messages
  • Business logic context preserved
  • Faster debugging and resolution
  • Better developer experience
  • Forces thoughtful error handling

Real-World Examples

Configuration Loading

// Bad: What config? Which field?
let port = config.get("port").unwrap().parse::<u16>().unwrap();
// Good: Clear context for each potential failure
let port = config.get("port")
    .expect("Server port must be configured in config.toml")
    .parse::<u16>()
    .expect("Server port must be a valid number between 1-65535");

File Operations

// Bad: Which file? Why did it fail?
let contents = std::fs::read_to_string(path).unwrap();
// Good: Clear about what we were trying to do
let contents = std::fs::read_to_string(&config_path)
    .expect("Failed to read application config file - check file exists and permissions");

But What About Performance?

There is no performance difference. Both unwrap() and expect() compile to identical code in release builds. The error message is only constructed when the panic actually occurs.

The argument for unwrap() based on performance is simply wrong.

When to Use Each

// expect() - Almost always the right choice
let value = risky_operation().expect("Business-relevant context here");

// unwrap() - NEVER acceptable. Always use expect().

The Nuclear Option: Remove unwrap() Entirely

Rust should remove unwrap() from the language. Its existence enables lazy programming and creates a false choice between "quick and dirty" versus "proper error handling."

When developers have unwrap() available, they take the path of least resistance. This leads to production code filled with meaningless panic messages that waste countless hours of debugging time.

expect() does everything unwrap() does, but better. There is literally no valid reason for unwrap() to exist when expect() is available with zero performance overhead.

Remove the temptation. Remove unwrap().

Join the Movement

Ban unwrap() from your production code.

Add this to the root of your modules to block on build

#![deny(clippy::unwrap_used)]

Cargo.toml can configure clippy

# Cargo.toml
[lints.clippy]
unwrap_used = "deny"

And configure Clippy to disallow unwrap() in tests and constants:

# clippy.toml
allow-unwrap-in-consts = false
allow-unwrap-in-tests = false

allow-expect-in-tests = true

Your future self (and your teammates) will thank you when debugging becomes effortless instead of painful.

A ranty project by yaleman.