Why do I get the error "there is no reactor running, must be called from the context of Tokio runtime" even though I have #[tokio::main]?

I'm following the mdns Rust documentation and pasted the example code but it throws the following error:

thread 'main' panicked at 'there is no reactor running, must be called from the context of Tokio runtime'

Here's the code that I have:

use futures_util::{pin_mut, stream::StreamExt};
use mdns::{Error, Record, RecordKind};
use std::{net::IpAddr, time::Duration};

const SERVICE_NAME: &'static str = "_googlecast._tcp.local";

#[tokio::main]
async fn main() -> Result<(), Error> {
    // Iterate through responses from each Cast device, asking for new devices every 15s
    let stream = mdns::discover::all(SERVICE_NAME, Duration::from_secs(15))?.listen();
    pin_mut!(stream);

    while let Some(Ok(response)) = stream.next().await {
        let addr = response.records().filter_map(self::to_ip_addr).next();

        if let Some(addr) = addr {
            println!("found cast device at {}", addr);
        } else {
            println!("cast device does not advertise address");
        }
    }

    Ok(())
}

fn to_ip_addr(record: &Record) -> Option<IpAddr> {
    match record.kind {
        RecordKind::A(addr) => Some(addr.into()),
        RecordKind::AAAA(addr) => Some(addr.into()),
        _ => None,
    }
}

Dependencies:

[dependencies]
mdns = "1.1.0"
futures-util = "0.3.8"
tokio = { version = "0.3.3", features = ["full"] }

What am I missing? I tried looking online but haven't found how to create a reactor for this use case.


Solution 1:

You are using a newer version of Tokio, such as 0.3 or 1.x, and many packages, including mdns 1.1.0, rely on an older version of Tokio, such as 0.2.

% cargo tree -d
tokio v0.2.22
└── mdns v1.1.0
    └── example_project v0.1.0

tokio v0.3.3
└── example_project v0.1.0

For now, you will need to match versions of the Tokio runtime. The easiest way is to use Tokio 0.2 yourself. The tokio-compat-02 crate may also be useful in some cases.

See also:

  • Why is a trait not implemented for a type that clearly has it implemented?

Various error messages with the same root cause:

there is no reactor running, must be called from the context of a Tokio 1.x runtime

there is no reactor running, must be called from the context of Tokio runtime

not currently running on the Tokio runtime

Solution 2:

Fix for me was adding this to Cargo.toml:

[dependencies]
async-std = { version = "1", features = ["attributes", "tokio1"] }

https://github.com/ATiltedTree/ytextract/issues/25

Solution 3:

At the time of writing, a fair amount of crates are already using Tokio v1, but others might still be under an experimental phase. Check your crates for prerelease versions which might have already upgraded their tokio runtime compatibility.

A relevant example of this is actix-web, which uses runtime 1.0 of Tokio since version 4, still in beta.

actix-web = { version = "4.0.0-beta.10" }