Why does my axum handler not implement Handler?

Every one of these handler functions below fail with essentially the exact same error “Handler is not satisfied”:

use axum::{extract::Request, http::HeaderMap, routing::get, Json, Router};

fn routes() -> Router {
    Router::new()
        .route("/a", get(foo_a))
        .route("/b", get(foo_b))
        .route("/c", get(foo_c))
        .route("/d", get(foo_d))
        .route("/e", get(foo_e))
        .route("/f", get(foo_f))
}

struct MyExtractor;
struct MyResponse;
struct MyBody;

async fn foo_a(_: MyExtractor) -> &'static str {
    "hello world!"
}

async fn foo_b() -> MyResponse {
    MyResponse
}

async fn foo_c(body: Json<MyBody>) -> Json<MyBody> {
    body
}

async fn foo_d(_req: Request, _body: String) -> &'static str {
    "yum food"
}

async fn foo_e() -> &'static str {
    static LIST: std::sync::Mutex<Vec<i32>> = std::sync::Mutex::new(Vec::new());

    let _list = LIST.lock().unwrap();
    let _ = foo_b().await;
    drop(_list);

    "checked it twice"
}

async fn foo_f(_body: String, _headers: HeaderMap) -> &'static str {
    "foofy"
}
error[E0277]: the trait bound `fn(MyExtractor) -> impl Future<Output = &'static str> {foo_a}: Handler<_, _>` is not satisfied
   --> src/main.rs:5:26
    |
5   |         .route("/a", get(foo_a))
    |                      --- ^^^^^ the trait `Handler<_, _>` is not implemented for fn item `fn(MyExtractor) -> impl Future<Output = &'static str> {foo_a}`
    |                      |
    |                      required by a bound introduced by this call
    |
    = help: the following other types implement trait `Handler<T, S>`:
              <Layered<L, H, T, S> as Handler<T, S>>
              <MethodRouter<S> as Handler<(), S>>
note: required by a bound in `axum::routing::get`
   --> /home/kmdreko/.cargo/registry/src/index.crates.io-6f17d22bba15001f/axum-0.7.5/src/routing/method_routing.rs:385:1
    |
385 | top_level_handler_fn!(get, GET);
    | ^^^^^^^^^^^^^^^^^^^^^^---^^^^^^
    | |                     |
    | |                     required by a bound in this function
    | required by this bound in `get`
    = note: this error originates in the macro `top_level_handler_fn` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0277]: the trait bound `fn() -> impl Future<Output = MyResponse> {foo_b}: Handler<_, _>` is not satisfied
   --> src/main.rs:6:26
    |
6   |         .route("/b", get(foo_b))
    |                      --- ^^^^^ the trait `Handler<_, _>` is not implemented for fn item `fn() -> impl Future<Output = MyResponse> {foo_b}`
    |                      |
    |                      required by a bound introduced by this call
    |
    = help: the following other types implement trait `Handler<T, S>`:
              <Layered<L, H, T, S> as Handler<T, S>>
              <MethodRouter<S> as Handler<(), S>>
note: required by a bound in `axum::routing::get`
   --> /home/kmdreko/.cargo/registry/src/index.crates.io-6f17d22bba15001f/axum-0.7.5/src/routing/method_routing.rs:385:1
    |
385 | top_level_handler_fn!(get, GET);
    | ^^^^^^^^^^^^^^^^^^^^^^---^^^^^^
    | |                     |
    | |                     required by a bound in this function
    | required by this bound in `get`
    = note: this error originates in the macro `top_level_handler_fn` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0277]: the trait bound `fn(Json<MyBody>) -> impl Future<Output = Json<MyBody>> {foo_c}: Handler<_, _>` is not satisfied
   --> src/main.rs:7:26
    |
7   |         .route("/c", get(foo_c))
    |                      --- ^^^^^ the trait `Handler<_, _>` is not implemented for fn item `fn(Json<MyBody>) -> impl Future<Output = Json<MyBody>> {foo_c}`
    |                      |
    |                      required by a bound introduced by this call
    |
    = help: the following other types implement trait `Handler<T, S>`:
              <Layered<L, H, T, S> as Handler<T, S>>
              <MethodRouter<S> as Handler<(), S>>
note: required by a bound in `axum::routing::get`
   --> /home/kmdreko/.cargo/registry/src/index.crates.io-6f17d22bba15001f/axum-0.7.5/src/routing/method_routing.rs:385:1
    |
385 | top_level_handler_fn!(get, GET);
    | ^^^^^^^^^^^^^^^^^^^^^^---^^^^^^
    | |                     |
    | |                     required by a bound in this function
    | required by this bound in `get`
    = note: this error originates in the macro `top_level_handler_fn` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0277]: the trait bound `fn(axum::http::Request<Body>, String) -> impl Future<Output = &'static str> {foo_d}: Handler<_, _>` is not satisfied
   --> src/main.rs:8:26
    |
8   |         .route("/d", get(foo_d))
    |                      --- ^^^^^ the trait `Handler<_, _>` is not implemented for fn item `fn(axum::http::Request<Body>, String) -> impl Future<Output = &'static str> {foo_d}`
    |                      |
    |                      required by a bound introduced by this call
    |
    = help: the following other types implement trait `Handler<T, S>`:
              <Layered<L, H, T, S> as Handler<T, S>>
              <MethodRouter<S> as Handler<(), S>>
note: required by a bound in `axum::routing::get`
   --> /home/kmdreko/.cargo/registry/src/index.crates.io-6f17d22bba15001f/axum-0.7.5/src/routing/method_routing.rs:385:1
    |
385 | top_level_handler_fn!(get, GET);
    | ^^^^^^^^^^^^^^^^^^^^^^---^^^^^^
    | |                     |
    | |                     required by a bound in this function
    | required by this bound in `get`
    = note: this error originates in the macro `top_level_handler_fn` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0277]: the trait bound `fn() -> impl Future<Output = &'static str> {foo_e}: Handler<_, _>` is not satisfied
   --> src/main.rs:9:26
    |
9   |         .route("/e", get(foo_e))
    |                      --- ^^^^^ the trait `Handler<_, _>` is not implemented for fn item `fn() -> impl Future<Output = &'static str> {foo_e}`
    |                      |
    |                      required by a bound introduced by this call
    |
    = help: the following other types implement trait `Handler<T, S>`:
              <Layered<L, H, T, S> as Handler<T, S>>
              <MethodRouter<S> as Handler<(), S>>
note: required by a bound in `axum::routing::get`
   --> /home/kmdreko/.cargo/registry/src/index.crates.io-6f17d22bba15001f/axum-0.7.5/src/routing/method_routing.rs:385:1
    |
385 | top_level_handler_fn!(get, GET);
    | ^^^^^^^^^^^^^^^^^^^^^^---^^^^^^
    | |                     |
    | |                     required by a bound in this function
    | required by this bound in `get`
    = note: this error originates in the macro `top_level_handler_fn` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0277]: the trait bound `fn(String, HeaderMap) -> impl Future<Output = &'static str> {foo_f}: Handler<_, _>` is not satisfied
   --> src/main.rs:10:26
    |
10  |         .route("/f", get(foo_f))
    |                      --- ^^^^^ the trait `Handler<_, _>` is not implemented for fn item `fn(String, HeaderMap) -> impl Future<Output = &'static str> {foo_f}`
    |                      |
    |                      required by a bound introduced by this call
    |
    = help: the following other types implement trait `Handler<T, S>`:
              <Layered<L, H, T, S> as Handler<T, S>>
              <MethodRouter<S> as Handler<(), S>>
note: required by a bound in `axum::routing::get`
   --> /home/kmdreko/.cargo/registry/src/index.crates.io-6f17d22bba15001f/axum-0.7.5/src/routing/method_routing.rs:385:1
    |
385 | top_level_handler_fn!(get, GET);
    | ^^^^^^^^^^^^^^^^^^^^^^---^^^^^^
    | |                     |
    | |                     required by a bound in this function
    | required by this bound in `get`
    = note: this error originates in the macro `top_level_handler_fn` (in Nightly builds, run with -Z macro-backtrace for more info)

What are the rules for implementing handler functions? How can I find out why they are failing? Why aren’t these errors more helpful?

This is meant as a canonical target for common axum handler errors.

The best resources are spread between the axum::handler and axum::extract modules. The former has a section that enumerates handlers:

  • Are async fns.
  • Take no more than 16 arguments that all implement Send.
  • All except the last argument implement FromRequestParts.
  • The last argument implements FromRequest.
  • Returns something that implements IntoResponse.
  • If a closure is used it must implement Clone + Send and be 'static.
  • Returns a future that is Send. The most common way to accidentally make a future !Send is to hold a !Send type across an await.

Examples are always good so lets look at each function to see why they don’t work:

  • async fn foo_a(_: MyExtractor) -> &'static str {
        "hello world!"
    }
    

    This does not work since there is not a FromRequestParts or FromRequest implementation for MyExtractor.

  • async fn foo_b() -> MyResponse {
        MyResponse
    }
    

    This does not work since the return type does not implement IntoResponse.

  • async fn foo_c(body: Json<MyBody>) -> Json<MyBody> {
        body
    }
    

    This one is trickier because axum’s Json type does implement both FromRequest and IntoResponse, but it still fails because additional constraints were not met. This can affect a number of extractor types:

    • T must implement DeserializeOwned for Json<T> to implement FromRequest
    • T must implement Serialize for Json<T> to implement IntoResponse
    • T must be Clone for Extension<T> to implement FromRequestParts
    • T must implement DeserializeOwned for Path<T> to implement FromRequestParts
    • T must implement DeserializeOwned for Query<T> to implement FromRequestParts
    • many others
  • async fn foo_d(_req: Request, _body: String) -> &'static str {
        "yum food"
    }
    

    This one does not work because both Request and String implement FromRequest when only one of them is allowed. Otherwise both will attempt to consume the request body.

  • async fn foo_e() -> &'static str {
        static LIST: std::sync::Mutex<Vec<i32>> = std::sync::Mutex::new(Vec::new());
    
        let _list = LIST.lock().unwrap();
        let _ = foo_b().await;
        drop(_list);
    
        "checked it twice"
    }
    

    This one does not compile since the Future being returned is !Send. This can happen when a !Send type is used across an .await point.

    • A Mutex guard from the standard library does not implement Send. Use parking-lot or an async mutex.
    • An Rc does not implement Send and can be a common culprit.
    • many others
  • async fn foo_f(_body: String, _headers: HeaderMap) -> &'static str {
        "foofy"
    }
    

    This one only has one extractor that consumes the body, but it must go at the end. Here the HeaderMap extractor needs to be listed first.

  • not mentioned but there’s a whole concept of State that can propagate through routers and into handlers where a mismatch can cause the same error.


However, even if you know these rules, it may not be clear which one is in error. An extractor may have yet another constraint that you don’t know is missing. But the error message doesn’t give you any indication which part is wrong, so you could end up wasting type digging into a response problem, when ultimately you accidentally introduced a !Send type or something.

Is there a better option? Yes, axum provides a #[debug_handler] macro that you can annotate your failing handler functions with which will make it generate better errors. Though be sure to enable the "macros" feature:

axum = { version = "...", features = ["macros"] }
#[axum::debug_handler]
async fn foo_a(_: MyExtractor) -> &'static str {
    "hello world!"
}

Here is what the errors above look like when all handlers are annotated with #[debug_handler]:

error: Can't have two extractors that consume the request body. `Request<_>` and `String` both do that.
  --> src/main.rs:33:16
   |
33 | async fn foo_d(_req: Request, _body: String) -> &'static str {
   |                ^^^^

error: `String` consumes the request body and thus must be the last argument to the handler function
  --> src/main.rs:49:23
   |
49 | async fn foo_f(_body: String, _headers: HeaderMap) -> &'static str {
   |                       ^^^^^^

error[E0277]: the trait bound `for<'de> MyBody: serde::de::Deserialize<'de>` is not satisfied
  --> src/main.rs:28:22
   |
28 | async fn foo_c(body: Json<MyBody>) -> Json<MyBody> {
   |                      ^^^^ the trait `for<'de> serde::de::Deserialize<'de>` is not implemented for `MyBody`
   |
   = help: the following other types implement trait `serde::de::Deserialize<'de>`:
             bool
             char
             isize
             i8
             i16
             i32
             i64
             i128
           and 144 others
   = note: required for `MyBody` to implement `serde::de::DeserializeOwned`
   = note: required for `Json<MyBody>` to implement `FromRequest<()>`
   = help: see issue #48214

error[E0277]: the trait bound `MyResponse: IntoResponse` is not satisfied
  --> src/main.rs:23:21
   |
23 | async fn foo_b() -> MyResponse {
   |                     ^^^^^^^^^^ the trait `IntoResponse` is not implemented for `MyResponse`
   |
   = help: the following other types implement trait `IntoResponse`:
             Box<str>
             Box<[u8]>
             axum::body::Bytes
             Body
             axum::extract::rejection::FailedToBufferBody
             axum::extract::rejection::LengthLimitError
             axum::extract::rejection::UnknownBodyError
             axum::extract::rejection::InvalidUtf8
           and 121 others
note: required by a bound in `__axum_macros_check_foo_b_into_response::{closure#0}::check`
  --> src/main.rs:23:21
   |
23 | async fn foo_b() -> MyResponse {
   |                     ^^^^^^^^^^ required by this bound in `check`

error[E0277]: the trait bound `MyExtractor: FromRequestParts<()>` is not satisfied
  --> src/main.rs:18:19
   |
18 | async fn foo_a(_: MyExtractor) -> &'static str {
   |                   ^^^^^^^^^^^ the trait `FromRequestParts<()>` is not implemented for `MyExtractor`
   |
   = help: the following other types implement trait `FromRequestParts<S>`:
             <HeaderMap as FromRequestParts<S>>
             <Extension<T> as FromRequestParts<S>>
             <Method as FromRequestParts<S>>
             <axum::http::request::Parts as FromRequestParts<S>>
             <Uri as FromRequestParts<S>>
             <Version as FromRequestParts<S>>
             <ConnectInfo<T> as FromRequestParts<S>>
             <Extensions as FromRequestParts<S>>
           and 28 others
   = note: required for `MyExtractor` to implement `FromRequest<(), axum_core::extract::private::ViaParts>`
note: required by a bound in `__axum_macros_check_foo_a_0_from_request_check`
  --> src/main.rs:18:19
   |
18 | async fn foo_a(_: MyExtractor) -> &'static str {
   |                   ^^^^^^^^^^^ required by this bound in `__axum_macros_check_foo_a_0_from_request_check`

error: future cannot be sent between threads safely
  --> src/main.rs:37:1
   |
37 | #[axum::debug_handler]
   | ^^^^^^^^^^^^^^^^^^^^^^ future returned by `foo_e` is not `Send`
   |
   = help: within `impl Future<Output = &'static str>`, the trait `Send` is not implemented for `MutexGuard<'_, Vec<i32>>`
note: future is not `Send` as this value is used across an await
  --> src/main.rs:42:21
   |
41 |     let _list = LIST.lock().unwrap();
   |         ----- has type `MutexGuard<'_, Vec<i32>>` which is not `Send`
42 |     let _ = foo_b().await;
   |                     ^^^^^ await occurs here, with `_list` maybe used later
note: required by a bound in `__axum_macros_check_foo_e_future::check`
  --> src/main.rs:37:1
   |
37 | #[axum::debug_handler]
   | ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `check`
   = note: this error originates in the attribute macro `axum::debug_handler` (in Nightly builds, run with -Z macro-backtrace for more info)

It may take multiple passes of fixing, and the original error may still be listed, but these error messages produced by the attribute give you a much better indication than without.

Why aren’t these errors more helpful?

It has to do with the way that functions with differing numbers of parameters can be used to satisfy the same constraint. A naïve implementation would run into conflicts, so it requires some trickery. See the Q&A here for roughly how it is done. But in the end, all that is asked to the compiler is “does this function satisfy Handler” and the only effective answer by the compiler is “yes” (and it compiles) or “no” (and you get a generic error).

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật