CodeBlanks Logo Icon CodeBlanks

Adding context

Add context to errors with anyhow::Context.

Adding context

The message "invalid digit found in string" doesn't say what failed. A good error explains what was being done when it failed. In anyhow there are context and with_context for this:

use anyhow::{Context, Result};

fn port_oku(s: &str) -> Result<u16> {
    s.parse::<u16>()
        .with_context(|| format!("port okunamadı ({s})"))
}
// error: port okunamadı (99999)
// Caused by: number too large to fit in target type

Since with_context takes a closure, the message is produced only in the error case.

Context with std

Without an external crate, the same effect is achieved with map_err: you combine the lower error and the context into one message:

fn port_oku(s: &str) -> Result<u16, String> {
    s.parse::<u16>()
        .map_err(|e| format!("port okunamadı ({s}): {e}"))
}

println!("{:?}", port_oku("8080"));   // Ok(8080)

This turns the lower error into text; to keep the chain, we'll look at the source() method in the next lesson.

Practice Error with context

Write the port_oku function above with map_err. Print the result for "8080" with {:?} and the error for "99999" as plain text, on separate lines.

Starter code

main.rs
fn main() {
    // buraya yaz
}

Sample solution

main.rs
fn port_oku(s: &str) -> Result<u16, String> {
    s.parse::<u16>()
        .map_err(|e| format!("port okunamadı ({s}): {e}"))
}

fn main() {
    println!("{:?}", port_oku("8080"));
    if let Err(e) = port_oku("99999") {
        println!("{}", e);
    }
}

Expected output

Ok(8080)
port okunamadı (99999): number too large to fit in target type

Questions and answers

Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.

1 What should a context message mostly include?

  • The line number
  • The user's name
  • Nothing; the lower error is enough
  • The operation and the relevant input (file name, key, value) Correct answer

Explanation: The user should be able to find the problem from the message: "ayar.toml okunamadı" makes sense together with "No such file".

2 Lazy context

Question
s.parse::<u16>()
    .____(|| format!("port okunamadı ({s})"))
Answer
s.parse::<u16>()
    .with_context(|| format!("port okunamadı ({s})"))

Explanation: with_context produces the message only when there's an error.

3 Input and port_oku result

Term Meaning
"8080" Ok(8080)
"99999" number too large ...
"abc" invalid digit ...
"" cannot parse ... empty string

All lessons in Intermediate