Close Menu

    Subscribe to Updates

    Get the latest creative news from FooBar about art, design and business.

    What's Hot

    Sony Malaysia univels WF-1000XM6 for RM1599, RM350 off when you preorder it

    iOS 26.3 now lets you migrate to Android easier

    Samsung Galaxy S26 series to launch on 26 February 2026

    Facebook X (Twitter) Instagram
    • Artificial Intelligence
    • Business Technology
    • Cryptocurrency
    • Gadgets
    • Gaming
    • Health
    • Software and Apps
    • Technology
    Facebook X (Twitter) Instagram Pinterest Vimeo
    Tech AI Verse
    • Home
    • Artificial Intelligence

      Read the extended transcript: President Donald Trump interviewed by ‘NBC Nightly News’ anchor Tom Llamas

      February 6, 2026

      Stocks and bitcoin sink as investors dump software company shares

      February 4, 2026

      AI, crypto and Trump super PACs stash millions to spend on the midterms

      February 2, 2026

      To avoid accusations of AI cheating, college students are turning to AI

      January 29, 2026

      ChatGPT can embrace authoritarian ideas after just one prompt, researchers say

      January 24, 2026
    • Business

      The HDD brand that brought you the 1.8-inch, 2.5-inch, and 3.5-inch hard drives is now back with a $19 pocket-sized personal cloud for your smartphones

      February 12, 2026

      New VoidLink malware framework targets Linux cloud servers

      January 14, 2026

      Nvidia Rubin’s rack-scale encryption signals a turning point for enterprise AI security

      January 13, 2026

      How KPMG is redefining the future of SAP consulting on a global scale

      January 10, 2026

      Top 10 cloud computing stories of 2025

      December 22, 2025
    • Crypto

      How Polymarket Is Turning Bitcoin Volatility Into a Five-Minute Betting Market

      February 13, 2026

      Israel Indicts Two Over Secret Bets on Military Operations via Polymarket

      February 13, 2026

      Binance’s October 10 Defense at Consensus Hong Kong Falls Flat

      February 13, 2026

      Argentina Congress Strips Workers’ Right to Choose Digital Wallet Deposits

      February 13, 2026

      Monero Price Breakdown Begins? Dip Buyers Now Fight XMR’s Drop to $135

      February 13, 2026
    • Technology

      This MacBook Pro has a Touch Bar and is only $410 while stock lasts

      February 13, 2026

      Intel’s tough decision boosted AMD to record highs

      February 13, 2026

      Bundle deal! Ring Battery Doorbell and Outdoor Cam Plus (44% off)

      February 13, 2026

      Microsoft Store goes zero-clutter—through the command line

      February 13, 2026

      How Boll & Branch leverages AI for operational and creative tasks

      February 13, 2026
    • Others
      • Gadgets
      • Gaming
      • Health
      • Software and Apps
    Check BMI
    Tech AI Verse
    You are at:Home»Technology»Implementing Rust newtype for errors in axum
    Technology

    Implementing Rust newtype for errors in axum

    TechAiVerseBy TechAiVerseNovember 17, 2025No Comments9 Mins Read2 Views
    Facebook Twitter Pinterest Telegram LinkedIn Tumblr Email Reddit
    Implementing Rust newtype for errors in axum
    Share
    Facebook Twitter LinkedIn Pinterest WhatsApp Email

    Implementing Rust newtype for errors in axum

    Learning Rust: Custom Error types that actually work!

    Sun, November 16, 2025 – 9 min read

    TL;DR: GITHUB REPO. Tired of writing the same verbose error handling boilerplate in your Axum handlers? Me too! 🙄 By creating a custom AppError newtype that wraps anyhow::Error and implements IntoResponse + From, you can ditch all those ugly match statements and embrace the beautiful ? operator. Your handler functions go from messy error-matching shenanigans to clean, readable code that automatically converts any error into proper HTTP responses. It’s like magic, but with more crabs! 🦀


    Recently I’ve been digging a lot into the axum crate for any of my Rust web projects. There are plenty of options out there for Rust web applications, but it seems that we have all settled on Axum as the go to crate. Before you even start reading this, if you have not checked it out yet – do so now … I’ll wait.

    Okay, you’re back! Love it? YES! 🥳 Now, let’s talk about a learning project I am working on. Ever since I’ve discovered htmx I’ve been immersing myself in the world of web development with HATEOAS as my priority. Just the neatness of using hypermedia gives me a rush, and helps me with all that JavaScript fatigue. I do suggest you go and give hypermedia systems a read, a thing I have been doing over the past couple of weeks.

    So, in the spirit of this book, I was following along with building some hypermedia driven system. But instead of using Python and Flask as stated in the book, I’ve opted to put my crab hat on, and do it in Rust. Like the big boy I am. In this post I wont explain how I did that (link to a post from the future will go here), but rather explain how I used the amazing features of Rust to eliminate a lot of boilerplate code on my side.

    Errors Errors

    In order to be a good web builder, you want to make sure to return the proper HTTP status codes. (I’m looking at you 200 OK with an error message). So in my handler functions I make sure to explicitly return the Status code as part of my return tuple. Something like so:

    Ok((StatusCode::OK, Html("

    Hello World

    "
    )))
    // Or an Error: Err((StatusCode::INTERNAL_SERVER_ERROR, format!("Error processing hello world")))

    This would signal back to the user (and axum) that the request was either 200 OK, and here is the HTML, or 500 Internal Server Error and an angry string. Nifty!

    With the glory of Rust’s Result enum, we are equipped to handle any errors our back end may throw at us. So, I just match on call that can fail, and return something back depending on that Result.
    In practice, say in this handler function that finds a Contact by its ID in the database, it would look something like this:

    #[axum::debug_handler]
    async fn get_edit_contact(
        State(state): State<AppState>,
        Path(id): Path<i64>,
        // The function signature tells us what we expect back
    ) -> Result<(StatusCode, Html<String>), (StatusCode, String)> {
     
        // This call can fail so let's match its Result
        let contact = match Contact::find_by_id(&state.db, id).await {
            // We're good return back the `Contact` into the `contact` variable
            Ok(contact) => contact, 
            // We're NOT good, return the tuple with a status code of 500
            Err(e) => {
                return Err(
                    (
                    StatusCode::INTERNAL_SERVER_ERROR,
                    format!("Failed to find contact: {e}")
                    )
                )
            }
        };
     
        let edit_template = EditContactTemplate { contact };
     
        // This can also fail, but we dont need to store it into a variable,
        // we just need to return.
        match edit_template.render() {
            // Looks good, return the HTML and 200 OK
            Ok(html) => Ok((StatusCode::OK, Html(html))),
            // Again 500 Bad, be angry here
            Err(e) => {
                Err(
                    (
                    StatusCode::INTERNAL_SERVER_ERROR,
                    format!("Failed to render template: {e}")
                    )
                )
            }
        }
    }

    That is a lot of boilerplate code. While I do enjoy the verbosity of Rust (makes me feel all safe and cozy), this gets real old real fast. Especially when you have multiple handler functions, that invoke multiple different calls that can fail. Let’s bring in another amazing feature of rust the newtype pattern, and simplify this 👏

    Building my own Error type

    I wont go too much into newtypes, as there is an excellent guide that I encourage all of you to read. Simply put, they are thin wrappers that allow you to extend functionality of existing Types not native to your crate. And I am gonna use it to extend the implement the IntoResponse trait into a type I dubbed AppError. And then allow it (what ever the Error is) to be converted into anyhow::Error.

    Let’s first create this wrapper newtype:

    pub struct AppError(anyhow::Error);

    Here I am wrapping anyhow::Error into a new type called AppError. I could do the same for any other type, and just create a wrapper around it (ie. a Vec wrapper: struct Wrapper(Vec)). Now comes the fun part, implementing certain traits.

    To implement the IntoResponse trait from axum into this new type, we only need to implement the into_response function, which needs to return a Response type. Let’s look at some code:

    impl IntoResponse for AppError { // 1
        fn into_response(self) -> Response { // 2
            (StatusCode::INTERNAL_SERVER_ERROR, self.0.to_string()).into_response() // 3 
        }
    }

    And just like that we’ve implemented our own way of returning an error response from a handler function. Let me explain the code a bit:

    1. The implementation block for IntoResponse for AppError
    2. This is the only function needed for IntoResponse and we are simply returning a Response from the axum crate
    3. We just return a tuple of a StatusCode and a String coming from element 0 of the AppError struct. Oh, and convert all that into a Response

    Here is a bit more complicated version of the same code, this one uses a templating engine to return some nicely formatted web pages. This version just expands the above, but should demonstrate that this all works really nicely with the rest of your codebase.

    impl IntoResponse for AppError {
        fn into_response(self) -> axum::response::Response {
            // Returning a HTML page for an error
            let template = Error5xxTemplate { // 1
                // Select element 0, as that is our anyhow::Error string and convert it so it works with our template
                error: self.0.to_string(),
            };
            match template.render() { // 2
                // If the template render is successful, return the HTML page with the error
                Ok(html) => (StatusCode::INTERNAL_SERVER_ERROR, Html(html)).into_response(),
                // The render has failed catastrophically - just return some string
                Err(_) => (StatusCode::INTERNAL_SERVER_ERROR, "Internal Server Error").into_response(),
            }
        }
    }

    Okay, there is a lot more going on here. Most of it is the same as before, but let me break it down:

    1. Somewhere in my code base I have a Error5xxTemplate struct that I use with the askama templating crate
    2. I make sure the template renders okay, if so – return the 5xx error page, if not I just give a 500 error and the string back.

    Now that we have an IntoResponse implemented. Let’s give our AppError the ability to take errors from anywhere.

    Converting other error types

    To make AppError a bit more flexible, I wanted to be able to automatically convert any* (*I’ll come back to this in a bit) error type. Let’s look at some code and make sense of it:

    impl<E> From<E> for AppError // 1
    where
        E: Into::Error> // 2 
    {
        fn from(err: E) -> Self { // 3
            Self(err.into())
        }
    }

    We are taking advantage of a very powerful crate here, anyhow. Which allows us to work with errors in Rust way more efficiently. In our case we are using it’s popularity and other crates ability to convert into this Error type.

    Let me explain this line by line:

    1. We are implementing From for AppError. By using the generic type E we can have a wider implementation. This would be the equivalent of impl From for AppError. Which converts the sqlx::Error type into AppError
    2. This is the critical bit, and why it actually limits us to certain errors. By having this where clause, we only allow the generic type E to be the ones that already support the Into trait from anyhow::Error. Basically limiting us to types that already support the conversion into this error type.
    3. We only need to implement the from function that takes an error and returns itself back. By using the support mentioned above, we can just take the error and run an .into() conversion.

    By using this generic trait approach we are essentially creating the following Rust code:

    // SQLX:
    impl From::Error> for AppError {
        fn from(err: sqlx::Error) -> Self {
            Self(err.into()) // sqlx::Error -> anyhow::Error -> AppError
        }
    }
    // serde_json
    impl From::Error> for AppError {
        fn from(err: serde_json::Error) -> Self {
            Self(err.into()) // serde_json::Error -> anyhow::Error -> AppError
        }
    }
    // reqwest
    impl From::Error> for AppError {
        fn from(err: reqwest::Error) -> Self {
            Self(err.into()) // reqwest::Error -> anyhow::Error -> AppError
        }
    }
    // ...

    And so on … You get the picture!

    Actual implementation

    Okay, so we have our newtype AppError, it has all the things it needs to be converted to our Error type. How does it actually work? Well, let’s go back to our get_edit_contact handler function from before, and see what has changed:

    #[axum::debug_handler]
    async fn get_edit_contact(
        State(state): State<AppState>,
        Path(id): Path<i64>,
    ) -> Result<(StatusCode, Html<String>), AppError> {
        let contact = Contact::find_by_id(&state.db, id).await?; // sqlx::Error -> AppError
        let edit_template = EditContactTemplate { contact };
        let html = edit_template.render()?; // askama::Error -> AppError
        Ok((StatusCode::OK, Html(html)))
    }

    Whoa, that is way tighter than before. Yes, we are using the ? operator we propagate the errors up the call stack. Meaning the value of the Result returned by both Contact::find_by_id and .render() are returned back to axum as AppError newtypes.

    This means we no longer have to deal with error handling within the function itself, and we are just returning the same error type back. Since it is the same error type, both function handler and axum are happy with receiving it! 🥳 Huzzah!

    If you want to see the full codebase in action, you can check out my GitHub repo here. And please ignore the mess, this is just a learning repo! 🙏

    Share. Facebook Twitter Pinterest LinkedIn Reddit WhatsApp Telegram Email
    Previous ArticleAn official atlas of North Korea
    Next Article The Game Awards 2025 nominees include Clair Obscur, Hollow Knight: Silksong and Hades 2
    TechAiVerse
    • Website

    Jonathan is a tech enthusiast and the mind behind Tech AI Verse. With a passion for artificial intelligence, consumer tech, and emerging innovations, he deliver clear, insightful content to keep readers informed. From cutting-edge gadgets to AI advancements and cryptocurrency trends, Jonathan breaks down complex topics to make technology accessible to all.

    Related Posts

    This MacBook Pro has a Touch Bar and is only $410 while stock lasts

    February 13, 2026

    Intel’s tough decision boosted AMD to record highs

    February 13, 2026

    Bundle deal! Ring Battery Doorbell and Outdoor Cam Plus (44% off)

    February 13, 2026
    Leave A Reply Cancel Reply

    Top Posts

    Ping, You’ve Got Whale: AI detection system alerts ships of whales in their path

    April 22, 2025669 Views

    Lumo vs. Duck AI: Which AI is Better for Your Privacy?

    July 31, 2025258 Views

    6.7 Cummins Lifter Failure: What Years Are Affected (And Possible Fixes)

    April 14, 2025153 Views

    6 Best MagSafe Phone Grips (2025), Tested and Reviewed

    April 6, 2025111 Views
    Don't Miss
    Gadgets February 13, 2026

    Sony Malaysia univels WF-1000XM6 for RM1599, RM350 off when you preorder it

    Sony Malaysia univels WF-1000XM6 for RM1599, RM350 off when you preorder it Sony Malaysia has…

    iOS 26.3 now lets you migrate to Android easier

    Samsung Galaxy S26 series to launch on 26 February 2026

    This MacBook Pro has a Touch Bar and is only $410 while stock lasts

    Stay In Touch
    • Facebook
    • Twitter
    • Pinterest
    • Instagram
    • YouTube
    • Vimeo

    Subscribe to Updates

    Get the latest creative news from SmartMag about art & design.

    About Us
    About Us

    Welcome to Tech AI Verse, your go-to destination for everything technology! We bring you the latest news, trends, and insights from the ever-evolving world of tech. Our coverage spans across global technology industry updates, artificial intelligence advancements, machine learning ethics, and automation innovations. Stay connected with us as we explore the limitless possibilities of technology!

    Facebook X (Twitter) Pinterest YouTube WhatsApp
    Our Picks

    Sony Malaysia univels WF-1000XM6 for RM1599, RM350 off when you preorder it

    February 13, 20260 Views

    iOS 26.3 now lets you migrate to Android easier

    February 13, 20260 Views

    Samsung Galaxy S26 series to launch on 26 February 2026

    February 13, 20260 Views
    Most Popular

    7 Best Kids Bikes (2025): Mountain, Balance, Pedal, Coaster

    March 13, 20250 Views

    VTOMAN FlashSpeed 1500: Plenty Of Power For All Your Gear

    March 13, 20250 Views

    This new Roomba finally solves the big problem I have with robot vacuums

    March 13, 20250 Views
    © 2026 TechAiVerse. Designed by Divya Tech.
    • Home
    • About Us
    • Contact Us
    • Privacy Policy
    • Terms & Conditions

    Type above and press Enter to search. Press Esc to cancel.