#future returned by `func` is not `Send` | future cannot be sent between threads safely

5 messages · Page 1 of 1 (latest)

tidal kestrel
#

Full error output

36  | #[tauri::command]
    | ^^^^^^^^^^^^^^^^^ future returned by `greet` is not `Send`
...
48  |         .invoke_handler(tauri::generate_handler![greet])
    |                         ------------------------------- in this macro invocation
    |
    = help: the trait `std::marker::Send` is not implemented for `dyn StdError`
note: future is not `Send` as it awaits another future which is not `Send`
   --> src/functions.rs:76:19
    |
76  |     let results = stream.collect::<Vec<Result<TaskResult, Box<dyn std::error::Error>>>>().await;
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ await occurs here on type `Collect<BufferUnordered<futures::stream::Iter<std::vec::IntoIter<impl futures::Future<Output = Result<TaskResult, Box<(dyn StdError + 'static)>>>>>>, Vec<Result<TaskResult, Box<dyn StdError>>>>`, which is not `Send`
note: required by a bound in `ResultFutureTag::future`

I find this log helpful, but on my level of knowledge I cant finally find out where problem is.
My code

pub async fn handle_tasks(
    service: &Service, 
    tasks: Vec<Task>, 
    token: String
    ) -> Result<Vec<Result<TaskResult, Box<dyn std::error::Error>>>, Box<dyn std::error::Error>> {
    let mut v = Vec::new();
    for task in tasks.iter() {
        v.push(handle_task(token.clone(), &service, &task, 0)); // whatever func I put in this, error occurs anyway, so I think problem somewhere below
    }
    let stream = futures::stream::iter(v).buffer_unordered(100);
    let results = stream.collect::<Vec<Result<TaskResult, Box<dyn std::error::Error>>>>().await;
    Ok(results)
}

There are other layers above this function, but this error specifically from handle_tasks

carmine herald
#

Your issue is that Box<dyn std::error::Error>> is not send

#

but Box<dyn std::error::Error>> also doesn't implement serde::Serialize which is required for data we send back to JS

#

so what you need to do is to define your own custom error type that you return

#

something like

#[derive(Debug, thiserror::Error)]
enum Error {
  // have a variant for each possible error type here
  // like an io error for example
  #[error(transparent)]
  Io(#[from] std::io::Error)
}

// implement serialize
impl serde::Serialize for Error {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: serde::Serializer,
    {
        self.to_string().serialize(serializer)
    }
}