Future returned by `find_one_handler` is not `Send`

Hello, I am building a proof-of-concept, restful microservice using Rust, Axum, etc. The code that I am sharing simply implements finding a project in a memory resident vector.

When I use synchronous calls to fetch a project from Axum's async handler, everything works properly.
However, when I change my code to be async and add an await to the call that fetches the project in the handler, I receive the error, below. I've Googled it and read a lot about Send bounds and .awaits, but my head is spinning, and I cannot figure out how to correct the problem.

I'd appreciate your suggestions and thank you for your time and interest. Here is a link to a sample project: abitofhelp.shared / Trait And Await · GitLab

The primary file of interest is main.rs.

Thanks,
Mike


ERROR MESSAGE

error: future cannot be sent between threads safely
  --> src/main.rs:43:1
   |
43 | #[debug_handler]
   | ^^^^^^^^^^^^^^^^ future returned by `find_one_handler` is not `Send`
   |
   = help: the trait `Send` is not implemented for `dyn std::future::Future<Output = Result<Project, ApiError>>`
   = note: consider using `std::sync::Arc<dyn std::future::Future<Output = Result<Project, ApiError>>>`; for more information visit <https://doc.rust-lang.org/book/ch16-03-shared-state.html>
note: future is not `Send` as it awaits another future which is not `Send`
  --> src/main.rs:53:5
   |
53 | /     state
54 | |         .app_state
55 | |         .service
56 | |         .find_one(find_one_project_query)
   | |_________________________________________^ await occurs here on type `Pin<Box<dyn std::future::Future<Output = Result<Project, ApiError>>>>`, which is not `Send`
note: required by a bound in `__axum_macros_check_find_one_handler_future::check`
  --> src/main.rs:43:1
   |
43 | #[debug_handler]
   | ^^^^^^^^^^^^^^^^ required by this bound in `check`
   = note: this error originates in the attribute macro `debug_handler` (in Nightly builds, run with -Z macro-backtrace for more info)

The error is saying #[debug_handler] requires the future returned by state.app_state.service.find_one(...) to be Send.

But due to the definition of FindOneProjectUseCase

#[async_trait(?Send)]
pub trait FindOneProjectUseCase {
    async find_one(...) -> ... { ... }
}

it desugars to a return value from find_one of type dyn std::future::Future<Output = Result<Project, ApiError>> without Send bound.

So the solution is to remove ?Send from #[async_trait(?Send)] including definitions and impls. It means the return type is generated as dyn std::future::Future<Output = ...> + Send which satisfies the Send bound. Click the expand macro from the topright dropdown button to see the generated code of simplified versions: Rust Playground

2 Likes

Wow! I didn't know that expanding the macros in the Playground was possible! Thanks for the tip! :slight_smile:

Thank you for showing me how you unraveled the information in the error, too! I am going to make the changes and will report back and I want to dig in deeper to see the details that you've mentioned.

Thank you for your help, @vague!

1 Like

I've updated my app based on your recommendations and things are working perfectly! Thank you for helping with this issue!

Mike

1 Like