Chris
Chris

Reputation: 40641

Tokio error: "there is no reactor running" even with #[tokio::main] and a single version of tokio installed

when running code like this:

use futures::executor;
...
pub fn store_temporary_password(email: &str, password: &str) -> Result<(), Box<dyn Error>> {
  let client = DynamoDbClient::new(Region::ApSoutheast2);
  ...
  let future = client.put_item(input);
  executor::block_on(future)?; <- crashes here
  Ok(())
}

I get the error:

thread '<unnamed>' panicked at 'there is no reactor running, must be called from the context of a Tokio 1.x runtime

My main has the tokio annotation as it should:

#[tokio::main]
async fn main() {
  ...

My cargo.toml looks like:

[dependencies]
...
futures = { version="0", features=["executor"] }
tokio = "1"

My cargo.lock shows that i only have 1 version of both futures and tokio ("1.2.0" and "0.3.12" respectively).

This exhausts the explanations I found elsewhere for this problem. Any ideas? Thanks.

Upvotes: 7

Views: 8898

Answers (1)

Ibraheem Ahmed
Ibraheem Ahmed

Reputation: 13568

You have to enter the tokio runtime context before calling block_on:

let handle = tokio::runtime::Handle::current();
handle.enter();
executor::block_on(future)?;

Note that your code is violating the rule that async functions should never spend a long time without reaching a .await. Ideally, store_temporary_password should be marked as async to avoid blocking the current thread:

pub async fn store_temporary_password(email: &str, password: &str) -> Result<(), Box<dyn Error>> {
  ...
  let future = client.put_item(input);
  future.await?;
  Ok(())
}

If that is not an option, you should wrap any calls to store_temporary_password in tokio::spawn_blocking to run the blocking operation on a separate threadpool.

Upvotes: 6

Related Questions