Skip to content

#[debug_handler] doesn't improve error message for WithRejection #1337

@davidpdrsn

Description

@davidpdrsn

WithRejection<T, E> requires E to implement IntoResponse. If you forget that you get the familiar "handler not implemented" error and #[debug_handler] doesn't help:

use axum::extract::rejection::JsonRejection;
use axum::response::{IntoResponse, Response};
use axum::routing::{post, MethodRouter};
use axum::Json;
use axum_extra::extract::WithRejection;

#[tokio::main]
async fn main() {
    let _: MethodRouter = post(send);
}

#[axum_macros::debug_handler]
pub async fn send(
    _: WithRejection<Json<MessageSend>, ApiError>,
) -> Json<MessageSendResponse> {
    Json(MessageSendResponse { id: "".to_string() })
}

#[derive(serde::Deserialize)]
pub struct MessageSend {
    pub contents: String,
}

#[derive(serde::Serialize)]
pub struct MessageSendResponse {
    pub id: String,
}

#[derive(Debug, thiserror::Error)]
pub enum ApiError {
    #[error(transparent)]
    JsonExtractorRejection(#[from] JsonRejection),
}

// no `impl IntoResponse for ApiError`

The error message is

error[E0277]: the trait bound `fn(WithRejection<Json<MessageSend>, ApiError>) -> impl Future<Output = Json<MessageSendResponse>> {send}: Handler<_, _, _>` is not satisfied
   --> src/main.rs:9:32
    |
9   |     let _: MethodRouter = post(send);
    |                           ---- ^^^^ the trait `Handler<_, _, _>` is not implemented for `fn(WithRejection<Json<MessageSend>, ApiError>) -> impl Future<Output = Json<MessageSendResponse>> {send}`
    |                           |
    |                           required by a bound introduced by this call
    |
    = help: the following other types implement trait `Handler<T, S, B>`:
              <IntoHandler<H, T, S, B> as Handler<T, S, B>>
              <Layered<L, H, T, S, B> as Handler<T, S, B>>
              <Or<L, R, Lt, Rt, S, B> as Handler<(M, Lt, Rt), S, B>>
note: required by a bound in `post`
   --> /Users/davidpdrsn/.cargo/registry/src/github.com-1ecc6299db9ec823/axum-0.6.0-rc.1/src/routing/method_routing.rs:404:1
    |
404 | top_level_handler_fn!(post, POST);
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `post`
    = 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 `WithRejection<Json<MessageSend>, ApiError>: FromRequest<(), Body, _>` is not satisfied
  --> src/main.rs:14:8
   |
14 |     _: WithRejection<Json<MessageSend>, ApiError>,
   |        ^^^^^^^^^^^^^ the trait `FromRequest<(), Body, _>` is not implemented for `WithRejection<Json<MessageSend>, ApiError>`
   |
   = help: the trait `FromRequest<S, B>` is implemented for `WithRejection<E, R>`
note: required by a bound in `__axum_macros_check_send_0_from_request_check`

The generate code is

#[allow(warnings)]
fn __axum_macros_check_send_0_from_request_check<M>()
where
    WithRejection<Json<MessageSend>, ApiError>:
        ::axum::extract::FromRequest<(), axum::body::Body, M> + Send,
{
}

#[allow(warnings)]
fn __axum_macros_check_send_0_from_request_call_check() {
    __axum_macros_check_send_0_from_request_check();
}

For some reason the additional M type parameter changes rust's error message. If you remove that and instead generate

#[allow(warnings)]
fn __axum_macros_check_send_0_from_request_check()
where
    WithRejection<Json<MessageSend>, ApiError>:
        ::axum::extract::FromRequest<(), axum::body::Body> + Send,
{
}

The error message becomes

error[E0277]: the trait bound `ApiError: IntoResponse` is not satisfied
  --> src/main.rs:36:5
   |
36 | /     WithRejection<Json<MessageSend>, ApiError>:
37 | |         ::axum::extract::FromRequest<(), axum::body::Body> + Send,
   | |_________________________________________________________________^ the trait `IntoResponse` is not implemented for `ApiError`
   |

We could look into this and see if its possible to improve this.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-axum-macrosC-bugCategory: This is a bug.E-mediumCall for participation: Experience needed to fix: Medium / intermediate

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions