ControlFlow used across await doesn't implement Send?

I was using thiserror with the AWS Lambda Runtime, which requires Send trait. I just decided I wanted to add more context to my errors. So, naturally I used map_err and/or match on the Err and move it in the appropriate type.

But, somehow anything besides the ? Try operator results in a ControlFlow and so I'm stuck:

   = help: the trait `Send` is not implemented for `(dyn std::error::Error + 'static)`
note: future is not `Send` as this value is used across an await
  --> src/main.rs:550:26
   |
47 |                           .output(match serde_json::to_string(&obj) {
   |  _________________________________-
48 | |                             Ok(json) => Ok(json),
49 | |                             Err(err) => Err(MyError::Json {
50 | |                                 err,
51 | |                                 text: "More context".to_owned(),
52 | |                             }),
53 | |                         }?)
   | |__________________________- has type `ControlFlow<Result<Infallible, MyError>, std::string::String>` which is not `Send`
54 |                           .send()
55 |                           .await?;
   |                            ^^^^^ await occurs here, with the value maybe used later

So, is there no way to avoid ControlFlow and yet still accomplish changing the MyError to a different Enum variant the way I am intending?

ah ha! It's because I did the ControlFlow inside the output(..) builder.

Moving the operation outside of that closure resolved it. But, no idea why!

ControlFlow used across await doesn’t implement Send?

The problem isn't ControlFlow itself that isn't Send, if that’s what you were thinking... it must be something like e.g. MyError not being Send. How is MyError defined? The error message also calls out (dyn std::error::Error + 'static), so perhaps MyError has some variant with Box<dyn Error> (notably not Box<dyn Error + Send + Sync>)?


Feel free to share some code examples (e.g. the version of the code that works and the one that doesn't; and when ? is involved, the surrounding function’s return type would be nice to know as well), not just the error message, if you're interested in help figuring out the details. As your program description stands, it's a bit lacking in details/context :wink:

2 Likes

Thanks, it's a pretty typical thiserror enum variant:

#[error("Failed json parsing {err:?}, {text}")]
Json{#[source] err: serde_json::Error, text: String},

Sorry my posting was incomplete. Hopefully this helps.

I meant the whole type enum MyError, including all the other variants. Those are taken into consideration by the compiler to determine whether MyError, and ultimately a type like ControlFlow<Result<Infallible, MyError>, String> containing it, is Send.