gmelodie
gmelodie

Reputation: 452

Axum the trait Handler<_, _, _> is not implemented for fn item

While implementing a handler function for an Axum endpoint, I ran accross the following error

   --> qubic-rpc/src/lib.rs:90:38
    |
90  |         .route("/balances/{id}", get(routes::wallet_balance))
    |                                  --- ^^^^^^^^^^^^^^^^^^^^^^ the trait `Handler<_, _>` 
    |            is not implemented for fn item 
    |           `fn(axum::extract::Path<QubicWallet>) -> impl Future<Output = impl IntoResponse> {wallet_balance}`
    |
    |            required by a bound introduced by this call
    |

Here's the definition of wallet_balance:

pub async fn wallet_balance(Path(_wallet): Path<QubicWallet>) -> impl IntoResponse {
    (StatusCode::NOT_IMPLEMENTED, "Not implemented yet")
}

All my other endpoints work fine, code compiles when I comment out the .route("/balances/{id}", get(routes::wallet_balance)) line.

Update: I've heard one could use #[axum::debug_handler] to fix this but wasn't able to set it up (error: not defined). I also had this error happen before in other situations, but in those cases it was because I was calling the handler function instead of passing it.

Upvotes: 0

Views: 141

Answers (1)

gmelodie
gmelodie

Reputation: 452

I've done a bit of digging and found out that people have three main issues when this error usually arises:

  1. They forget to pass async to the handler function
  2. They call the function instead of passing it to the route fn e.g. .route("/balances/{id}", get(routes::wallet_balance()))
  3. My case: one of the types passed as arguments through extractors, in this case QubicWallet does not implement the Deserialize trait.

I was able to figure this out by using the debug_handler macro (readily explained here):

  1. Add the feature macros of the axum crate in your Cargo.toml
  2. Add the #[axum::debug_handler] macro to the problematic handler
#[axum::debug_handler]
pub async fn wallet_balance(Path(_wallet): Path<QubicWallet>) -> impl IntoResponse {
    (StatusCode::NOT_IMPLEMENTED, "Not implemented yet")
}
  1. Re-run the code to figure out what is causing the trait error. In my case:
error[E0277]: the trait bound `for<'de> QubicWallet: Deserialize<'de>` is not satisfied
  --> qubic-rpc/src/routes.rs:21:44
   |
21 | pub async fn wallet_balance(Path(_wallet): Path<QubicWallet>) -> impl IntoResponse {
   |                                            ^^^^ the trait `for<'de> Deserialize<'de>` 
   |               is not implemented for `QubicWallet`, which is required by 
   |               `axum::extract::Path<QubicWallet>: FromRequest<RPCState, _>`

Implementing Deserialize for QubicWallet fixed the issue.

Upvotes: 1

Related Questions