<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Error-Handling on</title><link>/tags/error-handling/</link><description>Recent content in Error-Handling on</description><generator>Hugo</generator><language>en</language><lastBuildDate>Sun, 28 Jul 2024 11:30:00 +0000</lastBuildDate><atom:link href="/tags/error-handling/index.xml" rel="self" type="application/rss+xml"/><item><title>Lesson 10: Production Error Architecture — Logging, reporting, recovery</title><link>/post/rust/rust-errors-production-patterns/</link><pubDate>Sun, 28 Jul 2024 11:30:00 +0000</pubDate><guid>/post/rust/rust-errors-production-patterns/</guid><description>&lt;p&gt;I shipped a Rust service to production once with great error types, proper &lt;code&gt;Result&lt;/code&gt; propagation, context chains — the whole nine yards. And then I couldn&amp;rsquo;t debug anything because every error got logged as a single flat string with no request ID, no trace correlation, and no distinction between &amp;ldquo;user sent bad input&amp;rdquo; and &amp;ldquo;our database is on fire.&amp;rdquo; Having good error &lt;em&gt;types&lt;/em&gt; is half the battle. The other half is what you &lt;em&gt;do&lt;/em&gt; with those errors when they reach the top of your stack.&lt;/p&gt;</description></item><item><title>Lesson 9: panic!, unwrap, expect — When crashing is correct</title><link>/post/rust/rust-errors-panic-strategy/</link><pubDate>Wed, 24 Jul 2024 07:55:00 +0000</pubDate><guid>/post/rust/rust-errors-panic-strategy/</guid><description>&lt;p&gt;There&amp;rsquo;s a pervasive myth in the Rust community that &lt;code&gt;unwrap()&lt;/code&gt; is always bad. I&amp;rsquo;ve seen code reviews where people mechanically replace every &lt;code&gt;unwrap()&lt;/code&gt; with a &lt;code&gt;match&lt;/code&gt; or &lt;code&gt;.expect()&lt;/code&gt;, even when the &lt;code&gt;unwrap()&lt;/code&gt; was perfectly correct. The truth is more nuanced: &lt;code&gt;panic!&lt;/code&gt; is a tool, and like any tool, the question isn&amp;rsquo;t &amp;ldquo;should I ever use it?&amp;rdquo; but &amp;ldquo;when is it the right choice?&amp;rdquo;&lt;/p&gt;
&lt;h2 id="what-panic-actually-does"&gt;What panic! Actually Does&lt;/h2&gt;
&lt;p&gt;When you call &lt;code&gt;panic!()&lt;/code&gt;, Rust does one of two things depending on your configuration:&lt;/p&gt;</description></item><item><title>Lesson 8: Adding Context — Error chains and backtraces</title><link>/post/rust/rust-errors-error-context/</link><pubDate>Sun, 21 Jul 2024 13:10:00 +0000</pubDate><guid>/post/rust/rust-errors-error-context/</guid><description>&lt;p&gt;Picture this: it&amp;rsquo;s 2 AM, your pager goes off, and the log says &lt;code&gt;&amp;quot;connection refused&amp;quot;&lt;/code&gt;. Connection to &lt;em&gt;what&lt;/em&gt;? From &lt;em&gt;where&lt;/em&gt;? During &lt;em&gt;which operation&lt;/em&gt;? That single error message is technically correct and practically useless. I&amp;rsquo;ve been in that exact situation enough times to develop strong opinions about error context. Every error in a production system should answer three questions: what happened, where did it happen, and what was the system trying to do when it happened.&lt;/p&gt;</description></item><item><title>Lesson 7: Library vs Application Error Strategy — They're not the same</title><link>/post/rust/rust-errors-library-vs-app/</link><pubDate>Thu, 18 Jul 2024 09:40:00 +0000</pubDate><guid>/post/rust/rust-errors-library-vs-app/</guid><description>&lt;p&gt;I learned this the hard way. I was building a parsing library and used &lt;code&gt;anyhow::Error&lt;/code&gt; as my error type in all public functions. A user opened an issue: &amp;ldquo;I can&amp;rsquo;t match on your errors to handle different parse failures differently.&amp;rdquo; They were right. I&amp;rsquo;d designed a library with application-level error handling, and it was a terrible experience for consumers. Took me a weekend to refactor everything to typed errors.&lt;/p&gt;
&lt;p&gt;Libraries and applications have fundamentally different error handling requirements. Mix them up and you&amp;rsquo;ll either frustrate your users or drown in unnecessary boilerplate.&lt;/p&gt;</description></item><item><title>Lesson 6: anyhow — When you don't care about the type</title><link>/post/rust/rust-errors-anyhow/</link><pubDate>Tue, 16 Jul 2024 16:20:00 +0000</pubDate><guid>/post/rust/rust-errors-anyhow/</guid><description>&lt;p&gt;There&amp;rsquo;s a dirty secret in Rust error handling: half the time, you don&amp;rsquo;t actually need typed errors. You need errors that are easy to create, easy to chain, and easy to print. That&amp;rsquo;s &lt;code&gt;anyhow&lt;/code&gt;. Same author as &lt;code&gt;thiserror&lt;/code&gt; (David Tolnay), completely different use case. Where &lt;code&gt;thiserror&lt;/code&gt; is for defining precise error types, &lt;code&gt;anyhow&lt;/code&gt; is for &lt;em&gt;using&lt;/em&gt; errors without ceremony.&lt;/p&gt;
&lt;h2 id="the-problem-anyhow-solves"&gt;The Problem anyhow Solves&lt;/h2&gt;
&lt;p&gt;Without &lt;code&gt;anyhow&lt;/code&gt;, when you have a function that can fail in multiple unrelated ways, you either:&lt;/p&gt;</description></item><item><title>Lesson 5: thiserror — Derive your way to clean errors</title><link>/post/rust/rust-errors-thiserror/</link><pubDate>Sun, 14 Jul 2024 10:00:00 +0000</pubDate><guid>/post/rust/rust-errors-thiserror/</guid><description>&lt;p&gt;After writing my third custom error type by hand — with the &lt;code&gt;Display&lt;/code&gt; impl, the &lt;code&gt;Error&lt;/code&gt; impl, the &lt;code&gt;From&lt;/code&gt; impls — I thought, &amp;ldquo;there has to be a better way.&amp;rdquo; There was. It&amp;rsquo;s called &lt;code&gt;thiserror&lt;/code&gt;, and it&amp;rsquo;s probably the most widely-used error handling crate in the Rust ecosystem. David Tolnay wrote it, which means it&amp;rsquo;s well-designed, well-maintained, and does exactly one thing with zero bloat.&lt;/p&gt;
&lt;h2 id="what-thiserror-does"&gt;What thiserror Does&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;thiserror&lt;/code&gt; is a derive macro that generates &lt;code&gt;Display&lt;/code&gt;, &lt;code&gt;Error&lt;/code&gt;, and &lt;code&gt;From&lt;/code&gt; implementations for your error types. It produces the exact same code you&amp;rsquo;d write by hand — no runtime cost, no extra dependencies at runtime (it&amp;rsquo;s a proc-macro, so it&amp;rsquo;s only a compile-time dependency).&lt;/p&gt;</description></item><item><title>Lesson 4: Designing Custom Error Types — Your domain, your errors</title><link>/post/rust/rust-errors-custom-types/</link><pubDate>Thu, 11 Jul 2024 19:15:00 +0000</pubDate><guid>/post/rust/rust-errors-custom-types/</guid><description>&lt;p&gt;I once worked on a project where every error was &lt;code&gt;Box&amp;lt;dyn std::error::Error&amp;gt;&lt;/code&gt;. Debugging was miserable. When something failed in production, the logs said things like &amp;ldquo;invalid input&amp;rdquo; with zero context about &lt;em&gt;which&lt;/em&gt; input, &lt;em&gt;where&lt;/em&gt; in the pipeline, or &lt;em&gt;why&lt;/em&gt; it was invalid. That&amp;rsquo;s when I learned that good error types aren&amp;rsquo;t an afterthought — they&amp;rsquo;re part of your domain model.&lt;/p&gt;
&lt;h2 id="why-custom-error-types-matter"&gt;Why Custom Error Types Matter&lt;/h2&gt;
&lt;p&gt;Standard library errors like &lt;code&gt;io::Error&lt;/code&gt; and &lt;code&gt;ParseIntError&lt;/code&gt; are fine for what they describe. But your application has its own failure modes. A payment processor doesn&amp;rsquo;t just fail with &amp;ldquo;IO error&amp;rdquo; — it fails with &amp;ldquo;card declined,&amp;rdquo; &amp;ldquo;insufficient funds,&amp;rdquo; &amp;ldquo;gateway timeout,&amp;rdquo; &amp;ldquo;idempotency key conflict.&amp;rdquo; These are domain-specific failures that deserve domain-specific types.&lt;/p&gt;</description></item><item><title>Lesson 3: The ? Operator — Propagation made elegant</title><link>/post/rust/rust-errors-question-mark/</link><pubDate>Tue, 09 Jul 2024 14:30:00 +0000</pubDate><guid>/post/rust/rust-errors-question-mark/</guid><description>&lt;p&gt;Before the &lt;code&gt;?&lt;/code&gt; operator existed, Rust had &lt;code&gt;try!()&lt;/code&gt; — a macro that did the same thing but looked ugly and nested poorly. When &lt;code&gt;?&lt;/code&gt; landed in Rust 1.13, it was one of those rare language changes where everyone immediately agreed it was better. I remember refactoring an entire crate the same week, deleting dozens of &lt;code&gt;match&lt;/code&gt; blocks and &lt;code&gt;try!()&lt;/code&gt; calls, and the code just&amp;hellip; breathed.&lt;/p&gt;
&lt;h2 id="what--actually-does"&gt;What ? Actually Does&lt;/h2&gt;
&lt;p&gt;The &lt;code&gt;?&lt;/code&gt; operator is syntactic sugar for early return on error. When you write this:&lt;/p&gt;</description></item><item><title>Lesson 2: Result and Option — The foundation</title><link>/post/rust/rust-errors-result-option/</link><pubDate>Sun, 07 Jul 2024 08:45:00 +0000</pubDate><guid>/post/rust/rust-errors-result-option/</guid><description>&lt;p&gt;When I first started writing Rust, I used &lt;code&gt;match&lt;/code&gt; on every single &lt;code&gt;Result&lt;/code&gt; and &lt;code&gt;Option&lt;/code&gt;. My code looked like a staircase — match inside match inside match, indented halfway across the screen. Then a colleague showed me combinators, and suddenly the code read like prose instead of a tax form.&lt;/p&gt;
&lt;h2 id="result-more-than-just-ok-and-err"&gt;Result: More Than Just Ok and Err&lt;/h2&gt;
&lt;p&gt;You already know &lt;code&gt;Result&amp;lt;T, E&amp;gt;&lt;/code&gt; has two variants. But &lt;code&gt;Result&lt;/code&gt; comes with a &lt;em&gt;huge&lt;/em&gt; set of methods that let you transform, combine, and short-circuit without writing explicit &lt;code&gt;match&lt;/code&gt; blocks everywhere.&lt;/p&gt;</description></item><item><title>Lesson 1: Rust's Error Philosophy — No exceptions, no surprises</title><link>/post/rust/rust-errors-philosophy/</link><pubDate>Fri, 05 Jul 2024 11:23:00 +0000</pubDate><guid>/post/rust/rust-errors-philosophy/</guid><description>&lt;p&gt;I spent three years writing Java before I touched Rust. In Java, any function call might throw an exception — checked, unchecked, runtime, whatever. You never really &lt;em&gt;know&lt;/em&gt; what&amp;rsquo;s going to blow up until it does. The first time I wrote Rust code that forced me to handle every possible failure at the call site, I thought it was annoying. Six months later, I realized it was the sanest approach to errors I&amp;rsquo;d ever used.&lt;/p&gt;</description></item></channel></rss>