Close Menu

    Subscribe to Updates

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

    What's Hot

    Stop Killing Games is a consumer-driven shake up for digital distribution as a whole | Opinion

    Goat Simulator creators reveal new studio Feeble Minds

    Wreckreation maker Three Fields Entertainment puts whole studio on redundancy notice

    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

      Apple’s AI chief abruptly steps down

      December 3, 2025

      The issue that’s scrambling both parties: From the Politics Desk

      December 3, 2025

      More of Silicon Valley is building on free Chinese AI

      December 1, 2025

      From Steve Bannon to Elizabeth Warren, backlash erupts over push to block states from regulating AI

      November 23, 2025

      Insurance companies are trying to avoid big payouts by making AI safer

      November 19, 2025
    • Business

      Public GitLab repositories exposed more than 17,000 secrets

      November 29, 2025

      ASUS warns of new critical auth bypass flaw in AiCloud routers

      November 28, 2025

      Windows 11 gets new Cloud Rebuild, Point-in-Time Restore tools

      November 18, 2025

      Government faces questions about why US AWS outage disrupted UK tax office and banking firms

      October 23, 2025

      Amazon’s AWS outage knocked services like Alexa, Snapchat, Fortnite, Venmo and more offline

      October 21, 2025
    • Crypto

      HTX Research Releases New Report on Prediction Markets: From Structural Constraints to the Future of Attention-Based Financial Infrastructure

      December 4, 2025

      Monad (MON) Risks a Slide to Listing Lows as Big Players Walk Away — Last Hope At $0.028?

      December 4, 2025

      Peter Schiff to CZ: ‘Bitcoin Payments? They’re Just Liquidated Bets’

      December 4, 2025

      Tom Lee’s Relentless ETH Buying Puts BMNR Stock on a Possible 55% Breakout Path

      December 4, 2025

      Vienna Crypto Murder Shocks Europe as Kidnapping Wave Escalates

      December 4, 2025
    • Technology

      ‘AI is permeating everything we do’: How Guitar Center developed 2 AI tools this year

      December 4, 2025

      Media Briefing: Publishers turn to vertical video to compete with creators and grow ad revenue in 2026

      December 4, 2025

      From lawsuits to lobbying: How publishers are fighting AI

      December 4, 2025

      U.K. retailer Boots leads brand efforts to invest in ad creative’s data layer

      December 4, 2025

      Digiday+ Research Subscription Index 2025: Subscription strategies from Bloomberg, The New York Times, Vox and others

      December 4, 2025
    • 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 Read1 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

    ‘AI is permeating everything we do’: How Guitar Center developed 2 AI tools this year

    December 4, 2025

    Media Briefing: Publishers turn to vertical video to compete with creators and grow ad revenue in 2026

    December 4, 2025

    From lawsuits to lobbying: How publishers are fighting AI

    December 4, 2025
    Leave A Reply Cancel Reply

    Top Posts

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

    April 22, 2025475 Views

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

    July 31, 2025162 Views

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

    April 14, 202586 Views

    Is Libby Compatible With Kobo E-Readers?

    March 31, 202563 Views
    Don't Miss
    Gaming December 4, 2025

    Stop Killing Games is a consumer-driven shake up for digital distribution as a whole | Opinion

    Stop Killing Games is a consumer-driven shake up for digital distribution as a whole |…

    Goat Simulator creators reveal new studio Feeble Minds

    Wreckreation maker Three Fields Entertainment puts whole studio on redundancy notice

    Clair Obscur: Expedition 33 becomes 2025’s top third-party release on Xbox Game Pass

    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

    Stop Killing Games is a consumer-driven shake up for digital distribution as a whole | Opinion

    December 4, 20250 Views

    Goat Simulator creators reveal new studio Feeble Minds

    December 4, 20250 Views

    Wreckreation maker Three Fields Entertainment puts whole studio on redundancy notice

    December 4, 20250 Views
    Most Popular

    Apple thinks people won’t use MagSafe on iPhone 16e

    March 12, 20250 Views

    Volkswagen’s cheapest EV ever is the first to use Rivian software

    March 12, 20250 Views

    Startup studio Hexa acquires majority stake in Veevart, a vertical SaaS platform for museums

    March 12, 20250 Views
    © 2025 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.